ApiClient搭配ApiServer构成RPC框架。

Nuget包:NewLife.Core

源码地址:https://github.com/NewLifeX/X/blob/master/NewLife.Core/Remoting/ApiClient.cs

建议提前阅读:

此处为内容卡片,点击链接查看:https://newlifex.com/core/api_server

快速入门

新建控制台项目,写入以下代码:

using NewLife.Data;
using NewLife.Log;
using NewLife.Net;
using NewLife.Remoting;
using System;
using System.Linq;
using System.Net;

namespace NewLife.RPC
{
    class Program
    {
        static void Main(string[] args)
        {
            XTrace.UseConsole();

            var netUri = new NetUri(NetType.Tcp, IPAddress.Any, 5001);
            using var server = new ApiServer(netUri)
            {
                Log = XTrace.Log,
                EncoderLog = XTrace.Log,
                ShowError = true
            };
            server.Register<BigController>();
            server.Start();

            ClientTest();

            Console.ReadKey();
        }

        static void ClientTest()
        {
            var client = new MyClient("tcp://127.0.0.1:5001")
            {
                Log = XTrace.Log,
                EncoderLog = XTrace.Log
            };

            var rs = client.Invoke<Int32>("Big/Sum", new { a = 123, b = 456 });
            XTrace.WriteLine("{0}+{1}={2}", 123, 456, rs);
        }

        class MyClient : ApiClient
        {
            public MyClient(String urls) : base(urls) { }
            protected override void OnReceive(IMessage message)
            {
                if (Encoder.Decode(message, out var action, out _, out var args))
                {
                    XTrace.WriteLine("通知:{0} 参数:{1}", action, args.ToStr());
                }
            }
        }

        class BigController : IApi
        {
            public IApiSession Session { get; set; }

            public int Sum(int a, int b)
            {
                Task.Run(async () =>
                {
                    await Task.Delay(1000);

                    Session.InvokeOneWay("test", new { name = "Stone", company = "NewLife" }, 3);
                });

                return a + b;
            }
            public string ToUpper(string str) => str.ToUpper();

            public Packet Test(Packet pk)
            {
                var buf = pk.ReadBytes().Select(e => (Byte)(e ^ 'x')).ToArray();

                return buf;
            }
        }
    }
}

这里的重点是客户端调用:client.Invoke<Int32>("Big/Sum", new { a = 123, b = 456 })

新生命RPC框架的客户端调用,只有一个 Invoke (异步InvokeAsync),指定接口名并传入参数对象即可。这就是客户端的全部,没有描述文件生成代码,也不需要客户端服务端共用接口文件!

当然,只要你喜欢,可以搞一套接口,让客户端和服务端控制器都实现。这么做,比较麻烦的地方在于修改接口时需要同时改几个地方。客户端服务端还可以共享出入参模型类,这也是常见做法。由于默认采用Json序列化,因此两头可以使用各自的模型类,只要字段名对得上即可,完全避免了客户端服务端升级版本不匹配所带来的各种问题。


MyClient类继承自ApiClient,重写了 OnReceive 方法,所有未经处理的消息,都将进入这里。使用编码器解码后即可得到想要的数据。

作者:大石头 发布:2021-09-16 23:04:24 浏览:1,232)