游戏编程系列[1]--游戏编程中RPC协议的使用[2]--Aop PostSharp篇
上一篇我们使用了一个通用JSON协议约定来进行达到远程调用的目的。
但是从实现上,我们需要不断的在所有的方法上添加拦截,并且判断拦截,然后执行,这就达到了一个比较繁琐的目的。
之前我们尝试过使用代码生成器,直接生成。
构造基类,TestClassA
然后使用代码生成器,构造第二个类,TestClassAProxy。
所有需要的方法,我们都采用虚函数,然后重载,直接调用Base.Func();
这样也就完成了任务,这个方法的好处,代码生成简单,但是需要替换使用类别。
相对来说实现成本还比较低,对下面说的方法没什么信心的同学,可以采用这种实现方式。
然后我们说到到了本篇的主角,AOP利器 PostSharp
(额,商业软件,但是45天免费试用,我不会告诉你删了注册表后可以无限免费试用)
来看例子:
[Serializable] //[DebuggerNonUserCode] public sealed class ProxyAttribute : OnMethodBoundaryAspect { //[DebuggerNonUserCode] public override void OnException(MethodExecutionArgs args) { base.OnException(args); WindNet.RemoteCall.Instance.DoError(args.Exception); args.FlowBehavior = FlowBehavior.Continue; //不抛出 } //[DebuggerNonUserCode] public override void OnSuccess(MethodExecutionArgs args) { base.OnSuccess(args); WindNet.RemoteCall.Instance.DoCallBack(args.ReturnValue, __cid); } private WindNet.RPC.RequestObj __cid; //[DebuggerNonUserCode] public override void OnEntry(MethodExecutionArgs args) { var callback = args.Arguments.Last(); var methodName =args.Method.DeclaringType.Name + "." + args.Method.Name; var outargs = new List<object>(); for (int i = 0; i < args.Arguments.Count - 1; i++) { outargs.Add(args.Arguments[i]); } __cid = WindNet.RemoteCall.Instance.DoCall(callback as Delegate, args.Instance as IOpItem, methodName, outargs.ToArray()); if (WindNet.RemoteCall.Instance.IsLocal || __cid.isLocal) { //继续执行 } else { args.FlowBehavior = FlowBehavior.Return; } } }
然后我们在之前的方法上添加:
public class LocalTest { /// <summary> /// 添加一个消息 /// </summary> [Proxy] public static void AddMessage(string topic, string messageBody) { //这里什么都不干 } }
生成后反编译
public class LocalTest { public static void AddMessage(string topic, string messageBody) { MethodExecutionArgs methodExecutionArgs = new MethodExecutionArgs(null, new Arguments<string, string> { Arg0 = topic, Arg1 = messageBody }); MethodExecutionArgs arg_25_0 = methodExecutionArgs; MethodBase = <>z__a_3._2; arg_25_0.Method = ; <>z__a_3.a2.OnEntry(methodExecutionArgs); if (methodExecutionArgs.FlowBehavior != FlowBehavior.Return) { try { <>z__a_3.a2.OnSuccess(methodExecutionArgs); } catch (Exception exception) { methodExecutionArgs.Exception = exception; <>z__a_3.a2.OnException(methodExecutionArgs); switch (methodExecutionArgs.FlowBehavior) { case FlowBehavior.Default: case FlowBehavior.RethrowException: IL_81: throw; case FlowBehavior.Continue: methodExecutionArgs.Exception = null; return; case FlowBehavior.Return: methodExecutionArgs.Exception = null; return; case FlowBehavior.ThrowException: throw methodExecutionArgs.Exception; } goto IL_81; } } } }
帮我们正确的填写了缺失的部分。
优点:
简便,自动化,并且不需要去修改成代理类。
商业版,稳定性良好。
在VS中集成
缺点:
商业化,如果上线保险点还是去买一个。
Unity中,调试有点Bug,Pdb貌似有bug,兼容性问题。
如果不想用DLL,需要一些特殊手法才能在Unity中使用。
PS:不喜欢用商业产品,推荐用Fody,也有实现,回头有可能会切换到那个版本去。