另一种方法是使用 Unity 框架提供的拦截。通过拦截,您的类实现了一个接口,您将告诉框架每次在实现该接口的类上调用方法时,运行这些拦截器。您的拦截器代码可以查看被调用的方法是否以 set_ 为前缀。拦截器代码在到达函数的途中执行一次,在返回的路上执行一次。在回来的路上,你可以让拦截器调用过滤器方法(当然假设它是在接口上定义的)。
具体例子:
获取必备库
使用 NuGet 将 Unity 和 Unity 扩展添加到您的项目
定义要拦截的接口:SomeObject.cs
using System;
namespace InterceptSetter
{
interface ISomeObject
{
string SomeProperty { get; set; }
void Filter();
}
public class SomeObject : ISomeObject
{
public string SomeProperty { get; set; }
public void Filter()
{
Console.Out.WriteLine("Filter Called");
}
}
}
定义你的拦截行为:SetterCallsFilterMethodBehavior.cs
using Microsoft.Practices.Unity.InterceptionExtension;
using System;
using System.Collections.Generic;
using System.Linq;
namespace InterceptSetter
{
/// <summary>
/// See http://msdn.microsoft.com/en-us/library/ff660871(v=pandp.20).aspx
/// See http://msdn.microsoft.com/en-us/library/ff647107.aspx
/// </summary>
class SetterCallsFilterMethodBehavior : IInterceptionBehavior
{
public IEnumerable<Type> GetRequiredInterfaces()
{
// we dont need anything
return new[] { typeof(ISomeObject) };
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{ // Do not intercept non-setter methods
if (!input.MethodBase.Name.StartsWith("set_"))
return getNext()(input, getNext);
IMethodReturn msg = getNext()(input, getNext);
// post processing. this is where we call filter
if (input.Target is ISomeObject)
{
(input.Target as ISomeObject).Filter();
}
return msg;
}
/// <summary>
/// We always execute
/// </summary>
public bool WillExecute
{
get { return true; }
}
}
}
编写一个测试控制台程序:Program.cs
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
using System;
namespace InterceptSetter
{
class Program
{
static void Main(string[] args)
{
UnityContainer container = new UnityContainer();
container.AddNewExtension<Interception>();
container.RegisterType<ISomeObject, SomeObject>(
new Interceptor<TransparentProxyInterceptor>(),
new InterceptionBehavior<SetterCallsFilterMethodBehavior>());
// we must get our instance from unity for interception to occur
ISomeObject myObject = container.Resolve<ISomeObject>();
myObject.SomeProperty = "Hello Setter";
Console.ReadLine();
}
}
}
运行这个你会看到拦截器确实调用了过滤器方法(它打印到控制台)。
Unity 并不是唯一的依赖注入/拦截框架(google PostSharp)。Unity 是我熟悉的,所以这就是这个例子所使用的。
来源/另见:
- http://msdn.microsoft.com/en-us/library/ff660871(v=pandp.20).aspx - 描绘拦截流程的好图
- http://msdn.microsoft.com/en-us/library/ff647107.aspx - 显示不同拦截技术的细节过大