在声明式编程流行的今天,对于AOP中许多附加功能我们往往会通过声明一个Attribute更为直观的展示。比如需要添加一个LogHandler,那就定义一个LogSupportAttribute。Unity提供了自定义Attribute的匹配规则类型CustomAttributeMatchingRule。看一个简单示例:
1 public class MyObject 2 { 3 [LogSupport] 4 public virtual void DoWork() 5 { 6 7 } 8 9 public virtual void DoWork2() 10 { 11 12 } 13 } 14 15 [AttributeUsage(AttributeTargets.Method)] 16 public sealed class LogSupportAttribute : Attribute 17 { 18 19 } 20 21 public sealed class Log4NetHandler : ICallHandler 22 { 23 #region ICallHandler Members 24 25 public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) 26 { 27 Console.WriteLine(input.MethodBase.Name); 28 29 return getNext()(input, getNext); 30 } 31 32 public Int32 Order { get; set; } 33 34 #endregion 35 } 36 37 IUnityContainer unityContainer = new UnityContainer(); 38 39 unityContainer.LoadConfiguration(); 40 unityContainer.Configure<Interception>() 41 .AddPolicy(“CustomAttributeMatchingRule”) 42 .AddMatchingRule(new CustomAttributeMatchingRule(typeof(LogSupportAttribute), true)) 43 .AddCallHandler<Log4NetHandler>(); 44 unityContainer.RegisterType<MyObject>( 45 new Interceptor<VirtualMethodInterceptor>(), 46 new AdditionalInterface<INotifyPropertyChanged>(), 47 new InterceptionBehavior<PolicyInjectionBehavior>() 48 ); 49 50 MyObject myObject = unityContainer.Resolve<MyObject>(); 51 52 myObject.DoWork();
在上面的示例代码中定义了LogSupportAttribute,MyObject的DoWork函数添加了它,而DowWork2函数没有。执行后可以发现只有DoWork函数被拦截注入了Log4NetHandler。
CustomAttributeMatchingRule没有提供字符形式的构造函数来指定attributeType,在配置文件中获取System.Type类型的TypeConverter失败,导致在转换时无法将字符转换为实际的RuntimeType。不过你可以编写一个继承于CustomAttributeMatchingRule的类型,并通过new关键字隐藏Matches,然后加上一个字符形式的attributeType参数:
1 public class CustomAttributeMatchingRule2 : CustomAttributeMatchingRule 2 { 3 public CustomAttributeMatchingRule2(String attributeType, Boolean inherited) 4 : base(Type.GetType(attributeType), inherited) 5 { 6 7 } 8 9 public new Boolean Matches(MethodBase member) 10 { 11 return base.Matches(member); 12 } 13 }
基于CustomAttributeMatchingRule2的配置如下定义:
<unity xmlns=”http://schemas.microsoft.com/practices/2010/unity”> <sectionExtension type=”Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration” /> <assembly name=”mscorlib, 2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089″ /> <assembly name=”UnityTest6″ /> <namespace name=”System.ComponentModel” /> <namespace name=”UnityTest6″ /> <container> <extension type=”Interception” /> <interception> <policy name=”CustomAttributePolicy”> <matchingRule name=”CustomAttributeMatchingRule” type=”CustomAttributeMatchingRule2″> <constructor> <param name=”attributeType” value=”UnityTest6.LogSupportAttribute” /> <param name=”inherited” value=”true” /> </constructor> </matchingRule> <callHandler name=”Log4NetHandler” type=”Log4NetHandler” /> </policy> </interception> <register type=”MyObject”> <interceptor type=”VirtualMethodInterceptor” /> <addInterface type=”INotifyPropertyChanged” /> <interceptionBehavior type=”PolicyInjectionBehavior” /> </register> </container> </unity>