在.net framework 4中有一个DynamicObject 类型,我们通过重写 TryInvokeMember 方法实现简单的AOP

首先看类图:

Dynamicwarp

看下面的代码:

 public class DynamicWrapper : DynamicObject
    {
        private readonly object source;
 
        public DynamicWrapper(object source)
        {
            this.source = source;
        }
 
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            var methodInfo = source.GetType().GetMethod(binder.Name);
            if (methodInfo != null)
            {
                Func<object, object[], object> func = (s, a) => methodInfo.Invoke(s, a);
 
                result = MethodCall(func, source, args);
 
                return true;
            }
 
            result = null;
 
            return false;
        }
 
        protected virtual object MethodCall(Func<object, object[], object> func, object src, object[] args)
        {
            return func(src, args);
        }
    }

我们在上面代码继承下加上一个TRY CATCH实现一个TryCatchDynamicWrapper:

    public class TryCatchDynamicWrapper : DynamicWrapper
    {
        public TryCatchDynamicWrapper(object source)
            : base(source)
        { }
 
        protected override object MethodCall(Func<object, object[], object> func, object src, object[] args)
        {
            try
            {
                return base.MethodCall(func, src, args);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                throw;
            }
 
        }
    }

   然后我们写一个简单的测试方法,输入两个数相除,类图如下:

TestObject

代码是这样的,这里我们增一个扩展方法,这样使我们的代码更加简洁,您会在后面的Unit Test中看到:

   1:      public interface ITestObject
   2:      {
   3:          int Div(int num1, int num2);
   4:      }
   5:   
   6:      public class TestObject : ITestObject
   7:      {
   8:   
   9:          #region ITestObject Members
  10:   
  11:          public int Div(int num1,int num2)
  12:          {
  13:              return num1 / num2;
  14:          }
  15:   
  16:          #endregion
  17:   
  18:          public ITestObject WrapDynamicConsoleLogging
  19:          {
  20:              get
  21:              {
  22:                  return this.WithMethodConsoleLogging();
  23:              }
  24:          }
  25:      }
  26:   
  27:      public static class Extenstions
  28:      {
  29:          public static dynamic WithMethodConsoleLogging(this ITestObject testobject)
  30:          {
  31:              return new DynamicLoggingWrapper(Activator.CreateInstance<TestObject>(), ConsoleLogger.Instance);
  32:          }
  33:   
  34:          public static dynamic WrapWith<T>(this ITestObject testobject) where T : DynamicWrapper
  35:          {
  36:              return Activator.CreateInstance(typeof(T), new object[] { Activator.CreateInstance<TestObject>() });
  37:          }
  38:      }

Unit Test,如何使用呢:

   1:          [Test]
   2:          [ExpectedException(typeof(TargetInvocationException))]
   3:          public void TestTryCatchDynamicWrapper()
   4:          {
   5:              dynamic proxy = new TryCatchDynamicWrapper(new TestObject());
   6:              var ll = proxy.Div(6, 0);
   7:          }
   8:   
   9:          [Test]
  10:          [ExpectedException(typeof(TargetInvocationException))]
  11:          public void TestTryCatchDynamicWrapper2()
  12:          {
  13:              dynamic proxy = new TestObject().WrapWith<TryCatchDynamicWrapper>();
  14:              var ll = proxy.Div(6, 0);
  15:          }

注意到代码故意产生Exception来检测AOP是否有效。第二个方法使用扩展方法看上去更加简洁。当我们还可以写一个泛型版本的,看类图:

DynamicGenericarp

代码是这样的:

    public class DynamicGenericWrapper<T> : DynamicObject where T : class
    {
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            var methodInfo = typeof(T).GetMethod(binder.Name);
            if (methodInfo != null)
            {
                Func<object, object[], object> func = (s, a) => methodInfo.Invoke(s, a);
 
                result = MethodCall<T>(func, args);
 
                return true;
            }
 
            result = null;
 
            return false;
        }
 
        protected virtual object MethodCall<T>(Func<object, object[], object> func, object[] args)
        {
            var targetclass = Activator.CreateInstance<T>();
            return func(targetclass, args);
        }
    }
 
    public class TryCatchDynamicWrapper : DynamicWrapper
    {
        public TryCatchDynamicWrapper(object source)
            : base(source)
        { }
 
        protected override object MethodCall(Func<object, object[], object> func, object src, object[] args)
        {
            try
            {
                return base.MethodCall(func, src, args);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                throw;
            }
 
        }
    }

UnitTest:

   1:          [Test]
   2:          [ExpectedException(typeof(TargetInvocationException))]
   3:          public void TestTryCatchDynamicGenericWrapper()
   4:          {
   5:              dynamic proxy = new TryCatchDynamicGenericWrapper<TestObject>();
   6:              var ll = proxy.Div(6, 0);
   7:          }

这样我们实现.NET4 了简单的异常处理。您还可以继承DynamicWrapper实现事务,日志等功能。

您可以感兴趣文章:

使用Unity2.0的Interceptor实现简单AOP

使用EnterpriseLibrary的PIAB与Unity搭建简单AOP框架

希望这篇POST对您开发有帮助!


作者:Petter Liu
出处:http://www.cnblogs.com/wintersun/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
该文章也同时发布在我的独立博客中-Petter Liu Blog

posted on 2011-06-19 19:46  PetterLiu  阅读(3344)  评论(4编辑  收藏  举报