【发布时间】:2015-06-06 21:22:50
【问题描述】:
我正在尝试通过反射触发 PropertyChanged,但遇到了一些问题。
以下代码有效:
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string m_test = string.Empty;
public string Test
{
get
{
return m_test;
}
set
{
m_test = value;
Notify();
}
}
protected void Notify([CallerMemberName] string name = null)
{
var handler = PropertyChanged;
if (handler != null && name != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
public class ViewModel : ViewModelBase
{
private string m_test2 = string.Empty;
public string Test2
{
get
{
return m_test2;
}
set
{
m_test2 = value;
Notify();
}
}
}
但是,我已经向 INotifyPropertyChanged 添加了一个扩展方法,可以通过反射来提升它。
我可以调用this.Notify(),而不是Notify(),它的定义如下:
/// <summary>
/// Invoke sender's PropertyChanged event via Reflection
/// </summary>
/// <param name="sender">sender of the event</param>
/// <param name="prop">The Property name that has changed</param>
public static void NotifyPropertyChanged(this INotifyPropertyChanged sender, [CallerMemberName] string prop = null)
{
var senderType = sender.GetType();
var methodInfo = senderType.GetField("PropertyChanged", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (methodInfo != null)
{
var delegates = (MulticastDelegate)methodInfo.GetValue(sender);
if (delegates != null)
{
foreach (var handler in delegates.GetInvocationList())
{
handler.Method.Invoke(handler.Target, new object[] { sender, new PropertyChangedEventArgs(prop) });
}
}
}
}
不幸的是,GetField 在上面的示例中为 ViewModel 返回 null。
有没有办法反映父母的事件?
我正在考虑迭代基类,但我希望有更好/更简单的方法。
【问题讨论】:
-
也许这个答案会对你有所帮助:stackoverflow.com/a/586156/1466456 注意 Raise 扩展方法。
-
你做错了。这不是从课堂外部手动引发的有意义的事件,除非你的课堂存在导致事件在应该引发的时候不引发的错误。在这种情况下,如果是你的班级,只需修复这些错误。
-
@hvd 我不是在课堂之外提出的,我只是不想在每个实现
INotifyPropertyChanged的类上编写Notify方法。 -
您正在定义一个 ViewModelBase 类,因此从它继承的任何 VIewModel 都将具有该方法,您无需再次编写它。如果您有不想从 ViewModelBase 继承但又想实现 INotifyPropertyChanged 的类,则创建一个 NotifyPropertyBase 类。将 Notify() 方法放在那里,然后拥有 ViewModelBase 以及您从 NotifyPropertyBase 继承的任何其他内容。
-
即使将它放在一个 T4 模板中,为每个相关的基类(使用部分类)生成相同的
protected void Notify(string)实现也会比这种反射方法更好。无论如何它都不可靠:您的静态方法的 API 承诺它支持INotifyPropertyChanged的所有实现,但它实际上并不适用于所有这些实现,只适用于您自己的实现。即便如此,也需要在您的基类中添加一个 big 注释,即PropertyChanged由于无法通过反射进行验证而无法重构。
标签: c# inheritance reflection inotifypropertychanged