我不喜歡不符合標準的模式,但我正在對我的應用程序進行快速測試,並且碰到了這種奇怪的行爲。爲什麼WeakEventManager在發送者不是名義值時不會觸發事件?
考慮一個暴露事件的普通類,這裏是非常常見的PropertyChanged,但我認爲可以是任何其他類。
用戶選擇通過WeakEventManager助手訂閱事件。現在,「奇怪」的事情是實際的發件人引用:只要實例與訂閱時使用的實例相同,一切都會正常進行。但是,當您使用其他對象時,不會發出通知。
再一次,這是不是一個很好的模式,但我想知道是否有任何充分的理由這種限制,或者說,這是一種錯誤。好奇心比真正的需要更多。
class Class1
{
static void Main(string[] args)
{
var c = new MyClass();
WeakEventManager<INotifyPropertyChanged, PropertyChangedEventArgs>.AddHandler(
c,
"PropertyChanged",
Handler
);
c.ActualSender = c;
c.Number = 123; //will raise
c.ActualSender = new Class1();
c.Number = 456; //won't raise
Console.ReadKey();
}
static void Handler(object sender, PropertyChangedEventArgs e)
{
Console.WriteLine("Handled!");
}
}
class MyClass : INotifyPropertyChanged
{
public object ActualSender { get; set; }
private int _number;
public int Number
{
get { return this._number; }
set
{
if (this._number != value)
{
this._number = value;
this.OnPropertyChanged("Number");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(
string name
)
{
this.PropertyChanged(
this.ActualSender,
new PropertyChangedEventArgs(name)
);
}
}
編輯:這裏是一個粗略的方法來實現預期的行爲(爲了簡單起見,硬鏈接)。
class Class1
{
static void Main(string[] args)
{
var cx = new MyClass();
var cy = new MyClass();
Manager.AddHandler(cx, Handler1);
Manager.AddHandler(cx, Handler2);
Manager.AddHandler(cy, Handler1);
Manager.AddHandler(cy, Handler2);
cx.ActualSender = cx;
cx.Number = 123;
cx.ActualSender = new Class1();
cx.Number = 456;
cy.ActualSender = cy;
cy.Number = 789;
cy.ActualSender = new Class1();
cy.Number = 555;
Console.ReadKey();
}
static void Handler1(object sender, PropertyChangedEventArgs e)
{
var sb = new StringBuilder();
sb.AppendFormat("Handled1: {0}", sender);
var c = sender as MyClass;
if (c != null) sb.AppendFormat("; N={0}", c.Number);
Console.WriteLine(sb.ToString());
}
static void Handler2(object sender, PropertyChangedEventArgs e)
{
var sb = new StringBuilder();
sb.AppendFormat("Handled2: {0}", sender);
var c = sender as MyClass;
if (c != null) sb.AppendFormat("; N={0}", c.Number);
Console.WriteLine(sb.ToString());
}
}
static class Manager
{
private static Dictionary<object, Proxy> _table = new Dictionary<object, Proxy>();
public static void AddHandler(
INotifyPropertyChanged source,
PropertyChangedEventHandler handler
)
{
var p = new Proxy();
p._publicHandler = handler;
source.PropertyChanged += p.InternalHandler;
_table[source] = p;
}
class Proxy
{
public PropertyChangedEventHandler _publicHandler;
public void InternalHandler(object sender, PropertyChangedEventArgs args)
{
this._publicHandler(sender, args);
}
}
}
您是否檢查過'WeakEventManager'中的'NewListenerList'來查看仍然引用了哪些偵聽器 – 2014-09-03 09:50:07
檢查該方法看起來有點複雜,但是我嘗試使用memory-profiler並且似乎從未調用過(雖然不確定)。 – 2014-09-03 10:10:23