• 动态织入的AOP实现


    动态织入的AOP实现,有两种方法:

    第一类,借助于Remoting命名空间下的几个类,通过获取当前上下文及反射的机制来实现,这需要被AOP的类需要继承自arshalByRefObject或者ContextBoundObject;

    第二类,原理是基于动态代理的思想,即在运行时动态构造一个原有类的子类,这样就可以在子类的重载方法中插入额外代码。

    这两类方法,都有显著的不足,前者直接要求我们继承固定类,后者呢,除非父类方法被定义为virtual,或者方法定义于某个接口,否则就不能被重载,这就是得“拦截”并不是可以对任意的方法进行的。

    动态织入局限于CLR的限制,不能实现对任何方法进行AOP,如果要突破这个限制,只能采用静态织入的方法,静态织入采用。静态织入突破OO设计模式,可以拦截所有的方法甚至构造函数或属性访问器,因为它是直接修改IL。还有,因为它在运行前修改原有程序集,也就基本不存在运行时的性能损失问题了。它的不足,一方面是框架较复杂,实现较麻烦,依赖于对底层的IL指令集的操纵;

    一:继承自ContextBoundObject的实现

    帮助类:

        public class SecurityAspect : IMessageSink
        {
            internal SecurityAspect(IMessageSink next)
            {
                _next = next;
            }
    
            private IMessageSink _next;
    
            public IMessageSink NextSink
            {
                get { return _next; }
            }
    
            public IMessage SyncProcessMessage(IMessage msg)
            {
                Preprocess(msg);
                IMessage returnMethod = _next.SyncProcessMessage(msg);
                return returnMethod;
            }
    
            public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
            {
                throw new InvalidOperationException();
            }
    
            private void Preprocess(IMessage msg)
            {
                if (!(msg is IMethodMessage)) 
                    return;
                IMethodMessage call = msg as IMethodMessage;
                Type type = Type.GetType(call.TypeName);
                string callStr = type.Name + "." + call.MethodName;
                Console.WriteLine("Security validating : {0} for {1}", callStr,
                    Environment.UserName);
                // call some security validating code
            }
    
        }
    
        public class SecurityProperty : IContextProperty, IContributeObjectSink
        {
            public IMessageSink GetObjectSink(MarshalByRefObject o, IMessageSink next)
            {
                return new SecurityAspect(next);
            }
    
            public string Name
            {
                get { return "SecurityProperty"; }
            }
            public void Freeze(Context newContext)
            {
            }
            public bool IsNewContextOK(Context newCtx)
            {
                return true;
            }
        }
    
        [AttributeUsage(AttributeTargets.All)]
        public class SecurityAttribute : ContextAttribute
        {
            public SecurityAttribute() : base("Security") { }
            public override void GetPropertiesForNewContext(IConstructionCallMessage ccm)
            {
                ccm.ContextProperties.Add(new SecurityProperty());
            }
        }

    调用方:

        class Program
        {
            static void Main(string[] args)
            {
                SampleClass s = new SampleClass();
                s.DoSomething();
            }
        }
    
    
        [Security]
        [Tracing]
        public class SampleClass: ContextBoundObject
        {
            public void DoSomething()
            {
                Console.WriteLine("do something");
            }
        }

    二:Virtual方法及接口的实现

    帮助类:

        public class LogHandler : ICallHandler
        {
            /// <summary>
            /// 执行顺序
            /// </summary>
            public int Order { get; set; }
            public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
            {
                Console.WriteLine("方法名: {0}", input.MethodBase.Name);
                Console.WriteLine("参数:");
                for (var i = 0; i < input.Arguments.Count; i++)
                {
                    Console.WriteLine("{0}: {1}", input.Arguments.ParameterName(i), input.Arguments[i]);
                }
                Console.WriteLine("方法执行前的处理");
                var retvalue = getNext()(input, getNext);
                Console.WriteLine("方法执行后的处理");
                return retvalue;
            }
        }
    
        public class LogHandlerAttribute : HandlerAttribute
        {
            public override ICallHandler CreateHandler(IUnityContainer container)
            {
                return new LogHandler();
            }
        }

    调用方:

        public interface ISample
        {
            [LogHandler]
            void DoSomething();
            void DoSomethingNoAop();
        }
    
        class Sample1 : ISample
        {
            public void DoSomething()
            {
                Console.WriteLine("Sample1 do something");
            }
    
            public void DoSomethingNoAop()
            {
                Console.WriteLine("Sample1 do something no aop");
            }
        }
    
        public class SampleClass
        {
    
            [LogHandler]
            public virtual void SampleVirtual()
            {
                Console.WriteLine("Virtual method");
            }
    
            public void Sample()
            {
                Console.WriteLine("Sampe method");
            }
        }
    
        class Program {
    
            static void Main() {
                //针对接口
                var container1 = new UnityContainer()
                    .AddNewExtension<Interception>()
                    .RegisterType<ISample, Sample1>();
                container1
                    .Configure<Interception>()
                    .SetInterceptorFor<ISample>(new InterfaceInterceptor());
                container1
                    .Configure<Interception>()
                    .SetInterceptorFor<SampleClass>(new VirtualMethodInterceptor());
                var sample1 = container1.Resolve<ISample>();
                sample1.DoSomething();
                sample1.DoSomethingNoAop();
    
                //针对虚拟方法
                var sample2 = container1.Resolve<SampleClass>();
                sample2.SampleVirtual();
                sample2.Sample();
    
                Console.ReadKey();
            }
    
        }

    可以看到,第二种方法是用Unity实现的,关于Unity,这里多说两句:

    Unity的AOP可以从3种标记的情况拦截:
    TransparentProxyInterceptor:直接在类的方法上进行标记,但是这个类必须继承MarshalByRefObject;
    VirtualMethod:直接在类的虚方法上进行标记,如上文代码;
    InterfaceInterceptor:在接口的方法上进行标记,如上文代码;

    代码下载:ConsoleApplication1.rarConsoleApplication2.rar

  • 相关阅读:
    八大排序
    链表的合并
    记录B站yxc的背包九讲相关代码
    C++中多态实现
    YOLOV4所用到的一些tricks
    C++中的string 和 stringstream 的知识
    博客园中插入视频
    博客园中插入网页
    面试前必须要知道的【可重入锁 自旋锁】
    面试前必须要知道的【乐观锁 悲观锁】
  • 原文地址:https://www.cnblogs.com/luminji/p/2318211.html
Copyright © 2020-2023  润新知