在.net framework 4中有一个DynamicObject 类型,我们通过重写 TryInvokeMember 方法实现简单的AOP。
首先看类图:
看下面的代码:
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;
}
}
}
然后我们写一个简单的测试方法,输入两个数相除,类图如下:
代码是这样的,这里我们增一个扩展方法,这样使我们的代码更加简洁,您会在后面的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是否有效。第二个方法使用扩展方法看上去更加简洁。当我们还可以写一个泛型版本的,看类图:
代码是这样的:
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实现事务,日志等功能。
您可以感兴趣文章:
使用EnterpriseLibrary的PIAB与Unity搭建简单AOP框架
希望这篇POST对您开发有帮助!
作者:Petter Liu
出处:http://www.cnblogs.com/wintersun/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
该文章也同时发布在我的独立博客中-Petter Liu Blog。