BeetleX.XRPC是基于接口的远程通讯组件,它不紧可以把接口提供客户端调用,同样也支持服务端创建客户端的接口实例并主动调用客户端的方法.接口有着非常的规范性和约束性,但前提你是必须制定相应的接口并实现才行;为了让通讯在.NET平台使用变得更简便,在新版中组件支持远程委托调用.这功能不仅可以让客户端调用服务端的委托,同样也可以让服务端调用客户端的委托.

简介

组件支持任何委托的定义和调用包括框架集成的Action<T...>,Fun<T...,Result>和自定义委托.为了更好地满足通讯上的需求还是有一些简单的规规则约束;主要限制有:参数暂不支持refout,参数类型不能为Object因为无法进行反序列化处理.返回值必须是Task,Task<T>Void;为了在IO处理上更好地配合async/await来提高性能,组件要求返回值必须是TaskTask<T>,组件之所以支持Void主要是用于一些特别的场景,当委托为Void时是不会理会对端处理的情况(即发送后不管模式).还有组件对委托的参数也有限制,最大不能超过10个参数.

注册委托

组件提供了一致的方式来进行委托注册,方法如下:

AddDelegate<T>(T handler) where T : Delegate

注册方法是可以任意委托类型和对应的方法

//客户端
mClient = new XRPCClient("localhost", );
mClient.Options.ParameterFormater = new JsonPacket();
mClient.AddDelegate<Action<DateTime>>(SetTime);
//服务端
mServer.AddDelegate<ListEmployees>(() => Task.FromResult(DataHelper.Defalut.Employees));
mServer.AddDelegate<ListCustomers>(() => Task.FromResult(DataHelper.Defalut.Customers));

在绑定委托可以指定类函数也可以是匿名函数;当注册委托后对端就可以使用相同类型的Delegate进行代理和调用.

创建委托并调用

组件同样提供一致的方式来创建代理和调用

//客户端
mClient.Delegate<ListEmployees>()();
//服务端
mServer.Delegate<Action<DateTime>>(session)(DateTime.Now);

组件通过Delegate方法来创建相应委托代理,不过服务端在创建的时候必须指定客户端的session对象,创建委托后就可以直接调用.组件针缓存创建的委托代理,即使频繁地调用Delegate方法来创建也不用担心在创建过程中带来的损耗问题.

完整示例

上面已经描述了如何注册和对调用的使用,接下来做一个完全的数据查询示例来展示一下基于远程委托调用的便利性,为了满足这个示例的要求自定义了以下三个委托:

    public delegate Task<List<Order>> ListOrders(int employee, string employeeid);

    public delegate Task<List<Employee>> ListEmployees();

    public delegate Task<List<Customer>> ListCustomers();

这三个委托分别是:雇员,客户和订单查询.接下来就定义一个WPF的客户端程序通过调用这三个委托来进行数据查询的操作:

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
} XRPCClient mClient; private async void Window_Loaded(object sender, RoutedEventArgs e)
{
mClient = new XRPCClient("localhost", );
mClient.Options.ParameterFormater = new JsonPacket();
mClient.AddDelegate<Action<DateTime>>(SetTime);
comboEmployees.ItemsSource = from a in await mClient.Delegate<ListEmployees>()() select new { a.EmployeeID, Name = $"{a.FirstName} {a.LastName}" };
comboxCustomer.ItemsSource = await mClient.Delegate<ListCustomers>()();
lstOrders.ItemsSource = await mClient.Delegate<ListOrders>()(, null);
} private void SetTime(DateTime time)
{
this.Dispatcher.BeginInvoke(new Action<DateTime>(t =>
{
this.txtTime.Content = t.ToString();
}), time);
} private async void CmdSearch_Click(object sender, RoutedEventArgs e)
{
lstOrders.ItemsSource = await mClient.Delegate<ListOrders>()(
comboEmployees.SelectedValue != null ? (int)comboEmployees.SelectedValue : ,
comboxCustomer.SelectedValue != null ? (string)comboxCustomer.SelectedValue : null
);
}
}

为了展示服务端远程调客户端的,这里注册了一个Action<DateTime>用于服务端主动设置客户端时间的方法.

static void Main(string[] args)
{
var builder = new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
services.UseXRPC(s =>
{
s.ServerOptions.LogLevel = LogType.Warring;
s.RPCOptions.ParameterFormater = new JsonPacket();
},
c => {
c.AddDelegate<ListEmployees>(() => Task.FromResult(DataHelper.Defalut.Employees));
c.AddDelegate<ListCustomers>(() => Task.FromResult(DataHelper.Defalut.Customers));
c.AddDelegate<ListOrders>((emp, cust) =>
{
Func<Order, bool> filter = (o) => (emp == || o.EmployeeID == emp) && (String.IsNullOrEmpty(cust) || o.CustomerID == cust);
return Task.FromResult((from a in DataHelper.Defalut.Orders where filter(a) select a).ToList());
});
Task.Run(() =>
{
while (true)
{
foreach (var item in c.Server.GetOnlines())
{ c.Delegate<Action<DateTime>>(item)(DateTime.Now);
System.Threading.Thread.Sleep();
}
}
}); },
typeof(Program).Assembly);
});
builder.Build().Run();
}

以上是服务端的代码,注册了对应数据查询的委托,并开启一个简单的定时任务每秒中向所有客户端发送当前时间信息.接下来可以启动服务端和客户端运行结果如下:

从以上示例中可以发现,如果简单的数据传输处理,那用委托进行一个约束使用起的确是简便一些,毕竟.Net内置了一些委托类型可供使用无须自己定义,不过从应用规范上来说定义具体名称的委托或用接口来制定调用规范还是很有必要的. 如果你想获取完全示例可以访问:

https://github.com/IKende/BeetleX-Samples/tree/master/XRPC.DelegateInvoke

总结

.net core对wcf一直没有更好地支持,开发XRPC希望能在通讯实现这样一个类似的功能,现有版本的XRPC有.net core和std2.0 client.所以可以在.netcore,winform,wpf和支持std2.0的环境中应用.

BeetleX之XRPC远程委托调用的更多相关文章

  1. BeetleX之XRPC使用详解

    XRPC是基于BeetleX扩展一个远程接口调用组件,它提供基于接口的方式来实现远程服务调用,在应用上非常简便.组件提供.NETCore2.1和.NETStandard2.0的client版本,因此即 ...

  2. Thrift架构~从图中理解thrift,它事实上是一种远程过程调用

    thrift为我们简化了tcp通讯,它可以使用我们方便的建立各种语言的服务端与客户端,并实现客户端对服务器的远程过程调用,简单的说就是服务器通过thrift架构对外开放一些接口,并自己实现这些接口,如 ...

  3. XML-RPC远程方法调用

    一.简介 XML-RPC的全称是XML Remote Procedure Call,即XML远程方法调用. 它是一套允许运行在不同操作系统.不同环境的程序实现基于Internet过程调用的规范和一系列 ...

  4. Java RMI远程方法调用

    RMI(远程接口调用) 1. RMI的原理: RMI系统结构,在客户端和服务器端都有几层结构. 方法调用从客户对象经占位程序(Stub).远程引用层(Remote Reference Layer)和传 ...

  5. [转]Java远程方法调用

    Java远程方法调用,即Java RMI(Java Remote Method Invocation)是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口.它使客户机上运行的程序可以调用远 ...

  6. SmartRoute之远程接口调用和负载

    基于接口的调用远比基于基础消息交互来得更简单和便于维护,特别在业务展现上,接口作为业务表现更适合其便利性.为了让SmartRoute更适合业务应用集成,在新的一年开始SmartRoute集成了远程接口 ...

  7. SpringBoot里使用RMI进行远程方法调用

    一.Java RMI定义 Java RMI:Java远程方法调用,即Java RMI(Java Remote Method Invocation)是Java编程语言里,一种用于实现远程过程调用的应用程 ...

  8. 简单实现Java的RMI——远程方法调用

    一.RMI简介: 说到RMI就不得不说RPC了. RPC:(Remote Procedure Call),远程过程调用. RMI(Remote Method Invocation),远程方法调用. R ...

  9. SpringBoot关于系统之间的远程互相调用

    1.SpringBoot关于系统之间的远程互相调用 可以采用RestTemplate方式发起Rest Http调用,提供有get.post等方式. 1.1远程工具类 此处使用Post方式,参考下面封装 ...

随机推荐

  1. 十八、linux系统分区

    一.磁盘存储结构图:这里注意下,分区标有64字节,则每个分区有16字节,MBR引导分区有446字节,共有510字节,一个扇区有512字节,还有俩个字节是分区结束标识.比如隐藏文件等标识,都是这2个字节 ...

  2. Leetcode 5039. 移动石子直到连续

    第134次周赛 5039. 移动石子直到连续 5039. 移动石子直到连续 三枚石子放置在数轴上,位置分别为 a,b,c. 每一回合,我们假设这三枚石子当前分别位于位置 x, y, z 且 x < ...

  3. Image.FromStream(ms) 提示参数无效

    说明ms有问题,首先确保有读到数据,这种情况是保存到库的时候出错的. 原来你可能是这样写的: MemoryStream stream = new MemoryStream();PictureBox1. ...

  4. tomcat打印接口延迟时间

    项目中有些页面时延不稳定,需要看每次接口调用时延,怎么看,有两种方法:一种是直接去catalina.out日志中看,一种是直接去localhost_access_log日志中看,第一种需要在代码中实现 ...

  5. C++线程池的实现

    线程池,简单来说就是有一堆已经创建好的线程(最大数目一定),初始时他们都处于空闲状态,当有新的任务进来,从线程池中取出一个空闲的线程处理任务,然后当任务处理完成之后,该线程被重新放回到线程池中,供其他 ...

  6. python2查找匹配数据及类型转换

    判断一个字符是否包含在另一个字符串中,如果包含,但是数据类型不同,需要进行数据类型转换 下面这个是针对python2

  7. LeetCode Day 8

    LeetCode0015 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 例如, 给 ...

  8. mysql 索引和视图

    第五节:创建索引5.1 创建表的时候创建索引 CREATE TABLE 表名(属性名数据类型[完整性约束条件], 属性名数据类型[完整性约束条件], .... 属性名数据类型 [UNIQUE | FU ...

  9. 忘记mysql密码后重置密码

    https://jingyan.baidu.com/album/c275f6ba479ca9e33d7567ee.html?picindex=4 找不到mysql的my.ini文件问题: https: ...

  10. ACID原则

    ACID原则是数据库事务正常执行的四个,分别指原子性.一致性.独立性及持久性. 事务的原子性(Atomicity)是指一个事务要么全部执行,要么不执行.也就是说一个事务不可能只执行了一半就停止了.比如 ...