BeetleX之XRPC远程委托调用

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", 9090);
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", 9090);
        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>()(0, 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 : 0,
            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 == 0 || 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(1000);
                        }
                    }
                });

            },
            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的环境中应用.

原文地址:https://www.cnblogs.com/smark/p/12433398.html

时间: 2024-10-29 13:49:00

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

XML-RPC远程方法调用

一.简介 XML-RPC的全称是XML Remote Procedure Call,即XML远程方法调用. 它是一套允许运行在不同操作系统.不同环境的程序实现基于Internet过程调用的规范和一系列的实现. 这种远程过程调用使用http作为传输协议,XML作为传送信息的编码格式. Xml-Rpc的定义尽可能的保持了简单,但同时能够传送.处理.返回复杂的数据结构. xml rpc使用http协议做为传输协议的rpc机制,使用xml文本的方式传输命令和数据. 一个rpc系统,必然包括2个部分: 1

RMI - Java远程方法调用

一.入门篇 Java RMI指的是远程方法调用(Remote Method Invocation). 它是一种机制, 能够让不同操作系统之间程序实现方法调用. 比如: 一台电脑上的Java程序可以通过RMI调用另一台电脑上的方法(EJB底层就是使用RMI). 二.RMI和webservice RMI是在TCP协议上传递可序列化的Java对象, 只能用在Java虚拟机上, 客户端和服务端必须都是Java. webservice是在http协议上传递xml文件, 它与语言和平台无关, 可以在异构系统

SmartRoute之远程接口调用和负载

基于接口的调用远比基于基础消息交互来得更简单和便于维护,特别在业务展现上,接口作为业务表现更适合其便利性.为了让SmartRoute更适合业务应用集成,在新的一年开始SmartRoute集成了远程接口调用功能.基于SmartRoute的基础特性,在这基础上扩展的接口调用会变得更简单灵活,其特别点如下:并不需要知道服务地址,只需要明确接口和方法即可以实现远程服务调用:无需任何配置即可实现负载和故障迁移.而这一系列的更利功能都归攻于SmartRoute基础建设! SmartRoute的远程接口调用是

dubbo_远程同步调用原理

Dubbo缺省协议采用单一长连接和NIO异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况. Dubbo缺省协议,使用基于mina1.1.7+hessian3.2.1的tbremoting交互. 连接个数:单连接 连接方式:长连接 传输协议:TCP 传输方式:NIO异步传输 序列化:Hessian二进制序列化 适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压满提供者,尽量不要用dubbo协议传输大文件或超大字符串

EJB远程接口调用

一.EJB简介 EJB是sun的JavaEE服务器端组件模型,设计目标与核心应用是部署分布式应用程序.简单来说就是把已经编写好的程序(即:类)打包放在服务器上执行.凭借java跨平台的优势,用EJB技术部署的分布式系统可以不限于特定的平台.EJB (Enterprise JavaBean)是J2EE(javaEE)的一部分,定义了一个用于开发基于组件的企业多重应用程序的标准.其特点包括网络服务支持和核心开发工具(SDK). 在J2EE里,Enterprise Java Beans(EJB)称为J

spring整合RMI - Java远程方法调用

一. 开篇语 在上一篇RMI - Java远程方法调用博文中使用的是JDK原生类进行远程方法调用, 本篇文章使用spring提供的API对RMI进行整合, 希望能给您带来帮助. 二. 核心API 1. 客户端: 客户端的核心是RmiProxyFactoryBean, 它包含两个属性serviceUrl(远程调用地址), serviceInterface(远程调用接口) 2. 服务端: RmiServiceExporter把spring管理的Bean输出成一个RMI服务, 通过把Bean包装在一个

关于远程js调用phonegap注意

关于远程js调用phonegap本地原生代码注意: 把 cordova.js,和自己写的插件  xxxx.js放到服务器web目录下,然后在要引用的地方加入对应的<script src="path(对应目录地址)/xxx.js"></script>和<script src="path(对应目录地址)/cordova.js"></script> 对应原来在本地的cordova.js就可删了.

Java RMI远程方法调用

参考: 利用java-RMI进行大文件传输 RMI远程方法调用的简单方法和实例 RMI是类似RPC的一种远程方法调用协议,比RPC类型的WebService更简单,也可以跨进程访问 先来创建一个model或者javaBean,注意,该类必须实现序列化Serializable  public class Person implements Serializable {     private int id;     private String name;     private int age;

Android学习之远程绑定调用service

http://blog.csdn.net/q1234456gggg_jkjg/article/details/8479070 远程绑定调用service主要是用来不同进程的信息共享.就比如服务器和客户端,在服务器端设置好一个service提供方法或信息,然后客户端可以直 接调用服务器端service提供方法或信息.这里有个前提是客户端必须有和服务器端一份一样的AIDL,然后服务器端在客户端使用的系统上有注册过(也 就是安装运行过一次),之后客户端就可以远程绑定调用服务器端的service了. 具