我假设您的意思是使用自定义属性来指示要拦截的方法。您可以使用策略注入来通过XML配置来实现拦截。
首先,我们定义一个自定义属性:
[AttributeUsage(AttributeTargets.Method)]
public class MyInterceptionAttribute : Attribute
{
}
接下来我们可以创建一个ICallHandler来做一些拦截工作。此实现将仅在方法之前和之后执行 Console.WriteLine:
public class MyLoggingCallHandler : ICallHandler
{
IMethodReturn ICallHandler.Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
Console.WriteLine("Invoking " + input.MethodBase.Name);
IMethodReturn result = getNext()(input, getNext);
Console.WriteLine("Done Invoke");
return result;
}
int ICallHandler.Order { get; set; }
}
接下来假设我们有一些接口和实现:
public interface IMyClass
{
void Do();
void DoAgain();
}
public class MyClass : IMyClass
{
[MyInterception]
public void Do()
{
Console.WriteLine("Do!");
}
public void DoAgain()
{
Console.WriteLine("Do Again!");
}
}
请注意,我已将自定义属性 MyInterception 仅应用于 Do 方法,而不应用于 DoAgain 方法。我们将拦截对 Do 方法的所有调用。
接下来,我们创建配置来定义策略,配置匹配规则并注册类型和拦截器:
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<namespace name="UnityCallHandlerConfig" />
<assembly name="UnityCallHandlerConfig" />
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration"/>
<container>
<extension type="Interception"/>
<interception>
<policy name="Policy">
<matchingRule name="Match" type="Microsoft.Practices.Unity.InterceptionExtension.CustomAttributeMatchingRule, Microsoft.Practices.Unity.Interception">
<constructor>
<param name="attributeType" value="UnityCallHandlerConfig.MyInterceptionAttribute, UnityCallHandlerConfig" typeConverter="AssemblyQualifiedTypeNameConverter" />
<param name="inherited">
<value value="false"/>
</param>
</constructor>
</matchingRule>
<callHandler name="MyLogging" type="MyLoggingCallHandler">
<lifetime type="singleton"/>
</callHandler>
</policy>
</interception>
<register type="IMyClass" mapTo="MyClass">
<interceptor type="InterfaceInterceptor"/>
<interceptionBehavior type="PolicyInjectionBehavior"/>
</register>
</container>
</unity>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
</configuration>
我们还需要一个类型转换器将自定义属性的字符串表示形式转换为正确的类型:
public class AssemblyQualifiedTypeNameConverter : ConfigurationConverterBase
{
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (value != null)
{
Type typeValue = value as Type;
if (typeValue == null)
{
throw new ArgumentException("Cannot convert type", typeof(Type).Name);
}
if (typeValue != null) return (typeValue).AssemblyQualifiedName;
}
return null;
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
string stringValue = (string)value;
if (!string.IsNullOrEmpty(stringValue))
{
Type result = Type.GetType(stringValue, false);
if (result == null)
{
throw new ArgumentException("Invalid type", "value");
}
return result;
}
return null;
}
}
一旦我们完成所有设置,我们就可以创建一个容器并加载配置:
var container = new UnityContainer().LoadConfiguration();
var myClass = container.Resolve<IMyClass>();
myClass.Do();
myClass.DoAgain();
输出将是:
Invoking Do
Do!
Done Invoke
Do Again!
显示第一个方法被拦截,而第二个方法没有被拦截。