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

来源:互联网 发布:2017网络综艺发展趋势 编辑:程序博客网 时间:2024/06/06 11:44
  • 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");

    运行结果:

0 0
原创粉丝点击