从服务端生成代理
一、生成代理
在开发过程中,如果服务器和客户 端,都是我们自己开发的话(在同一个电脑),就可以使用本地代理生成。
调用下列代码,会将已注册的所有服务,导出代理为字符串。
RpcStore是实例,或者是IRpcParser的属性。
string code=RpcStore.GetProxyCodes("MyNameSpace"));
【示例1】 将代理字符串,写成.cs文件,然后通过链接的形式,将代码添加到客户端项目。
服务器代码,在服务器执行后,会在运行路径下,生成一个WhisperServers.cs的文件。
var service = new TcpTouchRpcService();
var config = new TouchSocketConfig()//配置
.SetListenIPHosts(new IPHost[] { new IPHost(port) })
.ConfigureContainer(a =>
{
a.AddConsoleLogger();
a.AddFileLogger();
})
.ConfigureRpcStore(a =>
{
a.RegisterServer<MyRpcServer>();//注册服务
#if DEBUG
File.WriteAllText("../../../WhisperServers.cs", a.GetProxyCodes("WhisperServers",new Type[] { typeof(TouchRpcAttribute) }));
#endif
})
.SetVerifyToken("TouchRpc");
service.Setup(config)
.Start();
然后打开需要引入的客户端解决方案。选择需要添加代理的项目,依次执行:
右击项目=>添加=>现有项
然后选择服务器生成的.cs文件,选择“添加”的下拉框,选择“添加为连接”。
最后确认文件被正确添加为链接。
这样,每次当服务有更新的时候,只需要启动一下服务器,代理就会自动刷新。
上述操作仅对客户端与服务器都在同一电脑上开发时才有效。
当不在同一个电脑上时,可将代理信息写成文件,直接发给客户端开发电脑。亦或者,为防止篡改生成的代码,不想把代理代码直接投入使用,那可以考虑将代码单独编译成dll,然后将编译的程序集发送。
上述行为,均是导出所有已注册的服务,当需要直接生成多个不同代理的源码时,可通过CodeGenerator静态类的相关方法直接生成。例如:
string codes=CodeGenerator.GetProxyCodes("Namespace",new Type[]{typeof(RpcServer) },new Type[] { typeof(TouchRpcAttribute)});
二、代理类型添加
通过之前的学习,大家可能大概明白了,在Rpc中,客户端与服务器在进行交互时,所需的数据结构不要求是同一类型,。所以在声明了服务以后,服务中所包含的自定义类型,会被复刻成结构相同的类型,但是这也仅仅局限于参数与服务相同程序集
的时候。如果服务中引入了其他程序集的数据结构,则不会复刻。
但是,往往在服务端开发中,会引入其他程序集,例如,我们习惯在项目中建立一个Models程序集,用于存放所有的实体模型,那是不是意味着客户端也必须引入这个程序集才能调用呢?没别的方法了?
答案,当然不是!!!
Rpc规范了两种方式来添加实体模型的复刻。
2.1 直接添加代理类型
在服务注册之前,任意时刻,可调用CodeGenerator.AddProxyType静态方法,添加代理类型,同时可传入一个bool值,表明是否深度搜索,比如,假如ProxyClass1中还有其他类型,则参数为True时,依然会代理。
CodeGenerator.AddProxyType<ProxyClass1>();
CodeGenerator.AddProxyType<ProxyClass2>(deepSearch:true);
或者直接按程序集添加
CodeGenerator.AddProxyAssembly(typeof(Program).Assembly);
2.2 通过特性标记添加
在需要代理的类上面声明RpcProxy标签,然后也可以重新指定代理类名。
[RpcProxy("MyArgs")]
public class Args
{
}
该场景可用于代理其他dll的自定义类型。
三、代理类型排除
默认情况下,与声明服务相同的自定义类型,会被代理复刻成结构相同的类型。但是有时候,我们希望服务端与客户端公用一个dll,所以就不需要复刻,那么可以排除代理类型。
CodeGenerator.AddIgnoreProxyType(typeof(Program));
或者直接按程序集排除
CodeGenerator.AddIgnoreProxyAssembly(typeof(Program).Assembly);
该场景可用于服务端与客户端公用一个实体dll,例如:当使用MemoryPack序列化的场景。