微信号:gh_98bfb3afe7eb

介绍:.net .net跳槽 c#跳槽 C#程序员 .net软件工程师 SQL Server 等等,本公众号为求职、发布求职信息、以及.net等相关技术的交流平台.

在.Net中实现自己的简易AOP

2017-01-05 23:10 DotNet开发跳槽
  • RealProxy基本代理类

    RealProxy类提供代理的基本功能。这个类中有一个GetTransparentProxy方法,此方法返回当前代理实例的透明代理。这是我们AOP实现的主要依赖。

    新建一个代理类MyProxy继承RealProxyIIntercept是我们自己实现的拦截器接口,内部只有一个Do方法

        private object _target; //当前代理实例
        private List<IIntercept> _intercepts; //拦截器
        MyProxy(object target, Type type,params IIntercept[] intercepts) : base(type)
        {
            _target = target;
            _intercepts = intercepts!=null? intercepts.ToList():null;
        }

    RealProxyInvoke方法会执行当前代理实例中方法,所以我们可以重写Invoke来实现AOP

    public override IMessage Invoke(IMessage msg){    var ctr = msg as IConstructionCallMessage;    if (ctr != null)//执行构造函数
        {
            Console.WriteLine("Construction");
            RealProxy _proxy = RemotingServices.GetRealProxy(this._target);
            _proxy.InitializeServerObject(ctr);
            MarshalByRefObject tp = (MarshalByRefObject)this.GetTransparentProxy();        return EnterpriseServicesHelper.CreateConstructionReturnMessage(ctr, tp);
        }    //执行当前代理实例方法
        if(_intercepts!=null)
        {        foreach (var _intercept in _intercepts)
            {
                _intercept.Do();
            }
        }    var call = msg as IMethodCallMessage;
        Console.WriteLine(string.Format("proxy method:{0}", call.MethodName));    var result = call.MethodBase.Invoke(this._target,call.Args);    return new ReturnMessage(result,new object[0],0,null,call);
    }

    封装代理类的实现,注意:RealProxy构造函数要求目标代理类必须必须从 MarshalByRef类型派生,所以我们需要继承 MarshalByRefObject类或者 ContextBoundObject

    public static class ActivatorContainer{    public static T Create<T>(params IIntercept[] intercepts)
        {         //构造函数不会被代理
            var result= Activator.CreateInstance(typeof(T));        var myProxy = new MyProxy(result, typeof(T), intercepts);        return (T)myProxy.GetTransparentProxy();
        }
    }var log = new LogIntercept();var time = new TimeIntercept();var hance = ActivatorContainer.Create<Person>(log,time);
    hance.Say("hello Proxy");

    运行结果:

    熟悉Castle的动态代理的同学可能会发现,我们自己实现的就像Castle的简易版,基于上面的代码我们也可以实现一个完善的动态代理

  • ProxyAttribute特性

    ProxyAttribute特性标志指示对象类型需要自定义代理。使用特性的相当于代替了上面的ActivatorContainer静态类来自动实现类的代理

    [AttributeUsage(AttributeTargets.Class)]public class MyProxyAttribute : ProxyAttribute{    private List<Type> _types; //拦截器
        //注:特性参数限制于bool, byte, char, double, float, int, long, short, string, System.Type, object, enum。
        public MyProxyAttribute(params Type[] types)    {
            _types = types?.ToList();
        }    public override MarshalByRefObject CreateInstance(Type serverType)    {
            System.Console.WriteLine("Start!");        var target= base.CreateInstance(serverType);
            List<IIntercept> intercepts = null;        if (_types!=null)
            {
                intercepts = new List<IIntercept>();
                intercepts.AddRange(_types.Select(s =>
                {                return (IIntercept)Activator.CreateInstance(s);
                }));
            } 
            var myProxy = new MyProxy(target, serverType, intercepts?.ToArray());        return (MarshalByRefObject)myProxy.GetTransparentProxy();
        }
    }

    此时,我们只要在需要代理的类上加上MyProxyAttribute标志,代理类需要继承 ContextBoundObject类,而不能是 MarshalByRefObject,然后直接new相关类就行了。此种实现方式构造函数也会被代理,可以通过特性参数注入拦截器类型来实现相关拦截器,相对于直接new拦截器来说更为方便,但不够灵活。但有一个好处就是如果没有继承ContextBoundObject类,目标类不会被代理,也不会不会报错。而上面的实现方式如果没有继承MarshalByRefObject类,运行则会报错。

    var hance = new Person();
    hance.Say("hello");

    运行结果:

来源:http://www.cnblogs.com/Cheer137/archive/2017/01/05/6253334.html


 
DotNet开发跳槽 更多文章 .NET Core 2.0版本预计于2017年春季发布 C# 程序中嵌入百度地图 C# 程序中嵌入百度地图 .NET Core 2.0版本预计于2017年春季发布 网上学习编程的七大趋势
猜您喜欢 Dev Daily: Mac中的.DS_Store文件是什么 测试建模 :从尔康的鼻孔说开来,重要的用例写三遍 三种姿势搞定组件依赖关系 当工程师收到了&nbsp;Bug&nbsp;Report 美国大选倒计时:R 语言和蒙特卡洛算法预测希拉里赢面高达89%