Можете ли вы сделать метод частью действия установщика по умолчанию в переменной свойства?
Если у вас есть несколько свойств, которые реализуют один и тот же метод в установщике, есть ли способ сделать его частью установщика по умолчанию?
Если у меня есть несколько свойств, которые вызывают Filter()
когда они установлены, есть ли способ вставить его в "базовый сеттер", чтобы у меня не было 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");
}
}
2 ответа
Другой способ сделать это - использовать перехват, подобный тому, который обеспечивается платформой 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). Единство - это то, с чем я знаком, так что этот пример использует.
Источники / Смотрите также:
- http://msdn.microsoft.com/en-us/library/ff660871(v=pandp.20).aspx - Хорошая диаграмма, изображающая поток перехвата
- http://msdn.microsoft.com/en-us/library/ff647107.aspx - излишнее количество деталей, показывающих различные методы перехвата
Вы можете создать универсальный метод установки и вызывать его из каждого метода установки:
private void Set<T>(ref T field, T value, string propertyName)
{
field = value;
Filter();
OnPropertyChanged(propertyName);
}
Тогда ваши свойства выглядят так:
public string SomeProperty
{
get { return this.someField; }
set
{
Set(ref this.someField, value, "SomeProperty");
}
}