游戏编程系列[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,也有实现,回头有可能会切换到那个版本去。

posted @ 2017-01-05 11:48  乐逐风  阅读(156)  评论(1编辑  收藏  举报