是否可以在F#中将INotifyPropertyChanged实现为类型扩展

时间:2014-10-27 17:08:45

标签: mvvm f# extension-methods inotifypropertychanged

在C#中,您可以实现基于PropertyChangedEventHandler的扩展方法,如下所示:

  static class VMExts
  {
    public static void RaisePropertyChanged(this PropertyChangedEventHandler handler, object sender, string propName)
    {
      if(handler != null)
      {
        handler(sender, new PropertyChangedEventArgs(propName));
      }
    }
  }

可以如下调用:

  class VM : INotifyPropertyChanged
  {
    private string _someText;

    public event PropertyChangedEventHandler PropertyChanged;

    public string SomeText
    {
      get { return _someText; }
      set
      {
        _someText = value;
        PropertyChanged.RaisePropertyChanged(this, "SomeText");
      }
    }
  }

我一直试图在F#中实现类似的功能,但无法弄清楚语法。 通过继承一些ViewModelBase样式类(例如http://www.fssnip.net/2x)来实现这一点显然很容易,但是使用扩展方法真的很不错。

所以,鉴于这个课程:

  type ViewModelBase() =
    let mutable _someText = ""
    let propertyChanged = Event<_, _>()

    interface INotifyPropertyChanged with
      [<CLIEvent>]
      member x.PropertyChanged = propertyChanged.Publish

    member x.SomeText 
      with get() = _someText
      and set(value) = 
        _someText <- value
        (x :> INotifyPropertyChanged).PropertyChanged.RaisePropertyChanged("SomeText")

我试过了:

  type PropertyChangedEventHandler with
    member x.RaisePropertyChanged(sender, propName) =
      if x <> null then
        x.Invoke(sender, PropertyChangedEventArgs(propName))

  open System.Runtime.CompilerServices

  [<Extension>]
  type VmExtensions() =
    [<Extension>]  
    static member inline RaisePropertyChanged(handler : PropertyChangedEventHandler, propName) =
      if handler <> null then
        handler.Invoke(handler, PropertyChangedEventArgs(propName))

我认为找不到这些对PropertyChanged有效,因为PropertyChanged的类型是IEvent,而我扩展了PropertyChangedEventHandler类型。

然后我尝试了:

  type IEvent<PropertyChangedEventHandler, PropertyChangedEventArgs> with
    member x.RaisePropertyChanged(sender, propName) =
      if x <> null then
        x.Invoke(sender, PropertyChangedEventArgs(propName))

但编译器并不喜欢IEvent的用法

  [<Extension>]
  type VmExtensions() =
    [<Extension>]  
    static member inline RaisePropertyChanged(handler : IEvent<PropertyChangedEventHandler, PropertyChangedEventArgs>, propName) =
//      if handler <> null then
        handler.Invoke(handler, PropertyChangedEventArgs(propName))

但IEvent确实只有一个Subscribe方法

由于

1 个答案:

答案 0 :(得分:4)

您可以通过Trigger方法(Event上未定义的IEvent方法提出事件:

[<Extension>]
type VmExtensions =
    [<Extension>]  
    static member inline RaisePropertyChanged
        (ev:Event<PropertyChangedEventHandler, _>, propName) =

        ev.Trigger(null, PropertyChangedEventArgs propName)