我试图编写一个类来避免像“RaisePropertyChanged”这样的方法。我知道我可以从具有该实现的类继承,但在某些情况下我不能。我尝试使用扩展方法,但Visual Studio抱怨。
public static class Extension
{
public static void RaisePropertyChanged(this INotifyPropertyChanged predicate, string propertyName)
{
if (predicate.PropertyChanged != null)
{
predicate.PropertyChanged(propertyName, new PropertyChangedEventArgs(propertyName));
}
}
}
它说:
“活动 ' System.ComponentModel.INotifyPropertyChanged.PropertyChanged'可以 仅出现在+ =或 - = “
的左侧
答案 0 :(得分:19)
Reed是对的。但是,我知道你要做的是什么(让你的代码可以重复使用 - 对你有益);我只想指出,通过接受PropertyChangedEventHandler
委托本身并在INotifyPropertyChanged
实施中传递它,通常可以轻松解决这个问题:
public static void Raise(this PropertyChangedEventHandler handler, object sender, string propertyName)
{
if (handler != null)
{
handler(sender, new PropertyChangedEventArgs(propertyName));
}
}
然后在你的类中实现INotifyPropertyChanged
,你可以像这样调用这个扩展方法:
PropertyChanged.Raise(this, "MyProperty");
这是有效的,因为as Marc said在类中声明了事件,你可以像字段一样访问它(这意味着你可以将它作为委托参数传递给方法,包括扩展名方法)。
答案 1 :(得分:11)
您只能从定义它的类中引发事件。
这一行:
predicate.PropertyChanged(propertyName, new PropertyChangedEventArgs(propertyName));
将失败,因为predicate
不是定义此扩展方法的类。
这部分原因通常是通过基类而不是使用Extension方法处理的。
答案 2 :(得分:4)
事件实际上只是一个带有添加/删除的API(技术上, 是CLI中提供的可选“调用”,但c#编译器不提供它。)
你所拥有的是一场类似田野的活动;类似字段的事件充当来自外部声明类型的添加/删除API,并且仅作为内部声明类型的字段,并且仅当它是时必要的作为委托 - 最常见的是:调用订阅者(这是c#4中的一个微妙变化;在c#4 所有访问内部之前) type对该字段起作用,包括+ = / - =)。
根据定义的扩展方法不能在声明类型中 - 只有顶级(非嵌套)静态类可以提供扩展方法;所以没有任何扩展方法永远可以直接调用类似字段的事件。
答案 3 :(得分:2)
当您使用event
关键字定义事件时,C#编译器实际上会在幕后为您生成许多内容。
event EventHandler MyEvent;
翻译成类似的东西(虽然不完全是因为它实际上增加了一些锁定和其他检查)......
private EventHandler _myEvent;
public EventHandler MyEvent
{
add( EventHandler handler )
{
_myEvent += handler;
}
remove( EventHandler handler )
{
_myEvent -= handler;
}
}
正如您所看到的,实际的EventHandler _myEvent
是私有的,无法直接调用。