Вы должны объявить свойство WhoCaresItsBroke
как виртуальное, иначе оно не будет переопределено вашим прокси-объектом. Если сделать его виртуальным, ваш обработчик на pto
будет вызван снова, потому что прокси-сервер делегирует вызов свойства своей цели.
Вам не нужно NotifyPropertyChangedAdvice
, вы можете удалить его. Требуемое поведение уже реализовано используемым классом ObservableObject
.
Если вы хотите, чтобы событие PropertyChanged
было запущено на прокси-сервере при возникновении целевого события PropertyChanged
, вы должны реализовать это вручную, как предложено в следующем разделе.
Взлом или обходной путь к огню PropertyChanged
на прокси и цель
Прокси-фабрика не связывает целевые события с аналогичными событиями на прокси, но вы можете сделать это вручную. Я не уверен, что я бы посоветовал вам сделать это, но вы могли бы использовать следующий хак.
Переписать свой прокси-завод и ProxyTypeObject
:
public class ProxyTypeObject : ObservableObject
{
private string whoCaresItsBroke;
// step 1:
// make the property virtual, otherwise it will not be overridden by the proxy
public virtual string WhoCaresItsBroke
{
// original implementation
}
public void PublicRaisePropertyChanged(string name)
{
RaisePropertyChanged(name);
}
}
public static class AopProxyFactory
{
public static object GetProxy(object target)
{
ProxyFactory factory = GetFactory(target);
object proxy = factory.GetProxy();
if(target is ProxyTypeObject)
{
// step 2:
// hack: hook handlers ...
var targetAsProxyTypeObject = (ProxyTypeObject)target;
var proxyAsProxyTypeObject = (ProxyTypeObject)proxy;
HookHandlers(targetAsProxyTypeObject, proxyAsProxyTypeObject);
}
return proxy;
}
private static void HookHandlers(ProxyTypeObject target, ProxyTypeObject proxy)
{
target.PropertyChanged += (sender, e) =>
{
proxy.PublicRaisePropertyChanged(e.PropertyName);
};
}
private static ProxyFactory GetFactory(object target)
{
var factory = new ProxyFactory(target);
// I simply add the advice here, but you could useyour original
// factory.AddAdvisor( ... )
factory.AddAdvice(new UnitValidationBeforeAdvice());
// You don't need this:
// factory.AddAdvice(new NotifyPropertyChangedAdvice());
factory.ProxyTargetType = true;
return factory;
}
}
Для этого требуется ProxyTypeObject
, чтобы иметь публично видимый метод для поднятия PropertyChangedEvent
; Вы, вероятно, должны сделать это по-другому, но это не главное.
Как это работает
Фабрика возвращает прокси типа ProxyTypeObject
, потому что вы установили factory.ProxyTargetType = true;
. Тем не менее, это все еще основанный на композиции прокси: после прокси у вас будет исходный объект (цель) и новый прокси-объект. И прокси, и цель имеют тип ProxyTypeObject
и могут вызывать событие PropertyChanged
.
На этом этапе при установке WhoCaresItsBroke
на прокси событие PropertyChanged
будет запускаться на вашем прокси, но не на цели. Целевое свойство не изменено.
шаг 1: объявить свойство виртуальным
Поскольку мы сделали свойство WhoCaresItsBroke
виртуальным, оно может быть переопределено в прокси. В переопределенном свойстве прокси-объект передает все WhoCaresItsBroke
вызовы свойству WhoCaresItsBroke
целевому объекту.
После этого шага вы увидите, что вызывается оригинальный обработчик, подключенный к вашему экземпляру pto
. Однако событие PropertyChanged
на прокси не вызывается.
шаг 2: подключить целевое событие к обработчику на прокси
Просто подключите целевое событие PropertyChanged
к обработчику на прокси, который вызывает свое собственное событие PropertyChanged
. Мы можем использовать то же имя, потому что в прокси мы можем предположить, что мы одного типа.