生成、获取代理
定义
命名空间:TouchSocket.Rpc
程序集:TouchSocket.Rpc.dll
一、为什么要生成代理
使用Rpc的原则就是像使用本地方法一样,让开发者感觉不到任何的不同。
但是我们的Rpc预留的接口都是Invoke
函数。也就是每次调用都必须手动传入参数和返回值类型,即使有InvokeT
的扩展调用,也很 容易出错。因为参数类型都是object
,所以可以无法进行良好的代码提示。
同时,当服务端更新时,例如:新增一个参数,或者修改了返回值类型,那么调用代码必须同步修改,不然就非常容易报错。
诸如此类的情况,会大大降低开发效率。
所以就必须把服务代理到本地,即生成调用接口代码,或者扩展调用代码。要实现此方式,常见的有三种,动态代理接口,静态织入,静态编译。三种方式殊途同归,最终都是构建本地数据结构,然后和远程通信。三种方式各有优缺,具体如下:
优缺点 | 动态代理接口 | 静态织入(源代码生成) | 静态编译 |
---|---|---|---|
优点 | 动态构建类,灵活、适应性强。 | 静态代码生成,自定义类参数自动生成,修改较灵活,调用效率高 | 自定义类参数自动生成,密封性强,安全性高,调用效率高。 |
缺点 | 调用效率较低,自定义类参数须自行构建,实现须IL支持,对调用平台有要求,例如:IOS不允许动态类生成,则不可使用。 | 项目代码管理难统一,强迫症猝死 | 服务一旦有破坏性升级,则必须重新替换dll,灵活性几乎为0。 |
二、从服务端生成代理
2.1 生成代理代码
在开发过程中,如果服务器和客户端,都是我们自己开发的话(在同一个电脑),则使用本地代理生成非常方便。如果不在一起,也没关系,可以直接把生成的cs文件直接复制到客户端项目。
使用的基本步骤如下:
- 在服务端生成.cs的代理文件。
- 将生成的.cs文件,复制到客户端项目(如果是同一电脑开发,则可以使用添加链接的方式编译)。
- 在客户端调用代理。
【示例1】 将代理字符串,写成.cs文件,然后通过链接的形式,将代码添加到客户端项目。
服务器代码,在服务器启动
后,会在运行路径下,生成一个RpcProxy.cs的文件。
var service = new TcpDmtpService();
var config = new TouchSocketConfig()//配置
.SetListenIPHosts(7789)
.ConfigureContainer(a =>
{
a.AddDmtpRouteService();
a.AddConsoleLogger();
a.AddRpcStore(store =>
{
store.RegisterServer<TestController>();
#if DEBUG
File.WriteAllText("RpcProxy.cs", store.GetProxyCodes("RpcProxy", new Type[] { typeof(DmtpRpcAttribute) }));
ConsoleLogger.Default.Info("成功生成代理");
#endif
});
})
.ConfigurePlugins(a =>
{
a.UseDmtpRpc();
a.Add<MyTouchRpcPlugin>();
})
.SetDmtpOption(new DmtpOption()
{
VerifyToken = "Rpc"//连接验证口令。
});
service.Setup(config);
service.Start();
RpcProxy.cs
字符串是代理文件路径,可以传入相对路径,也可以传入绝对路径。RpcProxy
是生成的代理代码的命名空间。typeof(DmtpRpcAttribute)
是需要生成的代理的服务类型。此处是以DmtpRpcAttribute
为标记的Rpc服务。如果是其他标记,请替换为对应标记的类型。
最后,生成代理的操作,最好使用DEBUG
预编译,因为这个功能仅在DEBUG模式我们才用得上。
然后打开需要引入的客户端解决方案。选择需要添加代理的项目,依次执行:
右击项目=>添加=>现有项
然后选择服务器生成的.cs文件,选择“添加”的下拉框,选择“添加为连接”。

最后确认文件被正确添加为链接。
这样,每次当服务有更新的时候,只需要启动一下服务器,代理就会自动刷新。
上述操作仅对客户端与服务器都在同一电脑上开发时才有效。
当不在同一个电脑上时,可将代理信息写成文件,直接发给客户端开发电脑。亦或者,为防止篡改生成的代码,不想把代理代码直接投入使用,那可以考虑将代码单独编译成dll,然后将编译的程序集发送。
上述行为,均是导出所有已注册的服务,当需要直接生成多个不同代理的源码时,可通过CodeGenerator静态类的相关方法直接生成。例如:
string codes=CodeGenerator.GetProxyCodes("Namespace",new Type[]{typeof(MyRpcServer) },new Type[] { typeof(DmtpRpcAttribute)});