BeetleX之XRPC远程委托调用
BeetleX.XRPC是基于接口的遠(yuǎn)程通訊組件,它不僅可以把接口提供客戶端調(diào)用,同樣也支持服務(wù)端創(chuàng)建客戶端的接口實(shí)例并主動調(diào)用客戶端的方法.接口有著非常的規(guī)范性和約束性,但前提你是必須制定相應(yīng)的接口并實(shí)現(xiàn)才行;為了讓通訊在.NET平臺使用變得更簡便,在新版中組件支持遠(yuǎn)程委托調(diào)用.這功能不僅可以讓客戶端調(diào)用服務(wù)端的委托,同樣也可以讓服務(wù)端調(diào)用客戶端的委托.
簡介
組件支持任何委托的定義和調(diào)用包括框架集成的Action<T...>,Fun<T...,Result>和自定義委托.為了更好地滿足通訊上的需求還是有一些簡單的規(guī)則約束;主要限制有:參數(shù)暫不支持ref和out,參數(shù)類型不能為Object因?yàn)闊o法進(jìn)行反序列化處理.返回值必須是Task,Task<T>或Void;為了在IO處理上更好地配合async/await來提高性能,組件要求返回值必須是Task和Task<T>,之所以支持Void主要是用于一些特別的場景,當(dāng)委托為Void時(shí)是不會理會對端處理的情況(即發(fā)送后不管模式).還有組件對委托的參數(shù)也有限制,最大不能超過10個(gè)參數(shù).
注冊委托
組件提供了一致的方式來進(jìn)行委托注冊,方法如下:
AddDelegate<T>(T handler) where T : Delegate注冊方法是可以任意委托類型和對應(yīng)的方法
//客戶端 mClient = new XRPCClient("localhost", 9090); mClient.Options.ParameterFormater = new JsonPacket(); mClient.AddDelegate<Action<DateTime>>(SetTime); //服務(wù)端 mServer.AddDelegate<ListEmployees>(() => Task.FromResult(DataHelper.Defalut.Employees)); mServer.AddDelegate<ListCustomers>(() => Task.FromResult(DataHelper.Defalut.Customers));在綁定委托可以指定類函數(shù)也可以是匿名函數(shù);當(dāng)注冊委托后對端就可以使用相同類型的Delegate進(jìn)行代理和調(diào)用.
創(chuàng)建委托并調(diào)用
組件同樣提供一致的方式來創(chuàng)建代理和調(diào)用
//客戶端 mClient.Delegate<ListEmployees>()(); //服務(wù)端 mServer.Delegate<Action<DateTime>>(session)(DateTime.Now);組件通過Delegate方法來創(chuàng)建相應(yīng)委托代理,不過服務(wù)端在創(chuàng)建的時(shí)候必須指定客戶端的session對象,創(chuàng)建建委托后就可以直接調(diào)用.
完整示例
接下來做一個(gè)完全的數(shù)據(jù)查詢示例來展示一下基于遠(yuǎn)程委托調(diào)用的便利性,為了滿足這個(gè)示例的要求自定義了以下三個(gè)委托:
public delegate Task<List<Order>> ListOrders(int employee, string employeeid);public delegate Task<List<Employee>> ListEmployees();public delegate Task<List<Customer>> ListCustomers();這三個(gè)委托分別是:雇員,客戶和訂單查詢.接下來就定義一個(gè)WPF的客戶端程序通過調(diào)用這三個(gè)委托來進(jìn)行數(shù)據(jù)查詢的操作:
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);} }為了展示服務(wù)端遠(yuǎn)程調(diào)客戶端的,這里注冊了一個(gè)Action<DateTime>用于服務(wù)端主動設(shè)置客戶端時(shí)間的方法.
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(); }以上是服務(wù)端的代碼,注冊了對應(yīng)數(shù)據(jù)查詢的委托,并開啟一個(gè)簡單的定時(shí)任務(wù)每秒中向所有客戶端發(fā)送當(dāng)前時(shí)間信息.接下來可以啟動服務(wù)端和客戶端運(yùn)行結(jié)果如下:
從以上示例中可以發(fā)現(xiàn),如果簡單的數(shù)據(jù)傳輸處理,那用委托進(jìn)行一個(gè)約束使用起的確是簡便一些,畢竟.Net內(nèi)置了一些委托類型可供使用無須自己定義,不過從應(yīng)用規(guī)范上來說定義具體名稱的委托或用接口來制定調(diào)用規(guī)范還是很有必要的. 如果你想獲取完全示例可以訪問:?https://github.com/IKende/BeetleX-Samples/tree/master/XRPC.DelegateInvoke
總結(jié)
以上是生活随笔為你收集整理的BeetleX之XRPC远程委托调用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2020 年 Service Mesh
- 下一篇: 五分钟了解Consul