如果你有多个属性在setter中实现相同的方法,有没有办法让它成为默认setter的一部分?
如果我有多个属性在设置时调用Filter(),是否有办法将其推入“基本setter”,这样我就不必在每个setter中调用Filter()?
private string _MyVal1; public string MyVal1 { get { return _MyVal1; } set { _MyVal1 = value; Filter(); OnPropertyChanged("MyVal1"); } } private string _MyVal2; public string MyVal2 { get { return _MyVal2; } set { _MyVal2 = value; Filter(); OnPropertyChanged("MyVal2"); } } private string _MyValN; public string MyValN { get { return _MyValN; } set { _MyValN = value; Filter(); OnPropertyChanged("MyValN"); } }
所以它变成了这样:
private string _MyValN; public string MyValN { get { return _MyValN; } set : FilterSetter { _MyValN = value; OnPropertyChanged("MyValN"); } }
解决方法@H_301_12@
执行此操作的另一种方法是使用Unity框架提供的拦截.通过拦截,您的类实现了一个接口,您将告诉框架每次在实现该接口的类上调用方法时,运行这些拦截器.您的拦截器代码可以查看被调用的方法是否以set_为前缀.拦截器代码在前往函数的路上执行一次,在返回途中执行一次.在回来的路上,你可以让拦截器调用filter方法(假设它在接口上定义).
具体例子:
获取先决条件库
使用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();
}
}
}
运行它你会看到拦截器确实调用了filter方法(打印到控制台).
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 – 显示不同拦截技术的细节过度
具体例子:
获取先决条件库
使用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(); } } }
运行它你会看到拦截器确实调用了filter方法(打印到控制台).
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 – 显示不同拦截技术的细节过度