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