문제

I need to implement the IDataErrorInfo interface in a base class. The interface requires a property and an indexer. I want to provide a default implementation for both and allow subclasses to override it. I can't seem to wield the syntax for a 'virtual' implementation with the syntax for interface implementation! For example:

type ViewModelBase() =
  interface IDataErrorInfo with
    abstract Error : string with get
    default this.Error with get() = ""

Gives the following compile errors

Error 1 Unexpected keyword 'abstract' in member definition. Expected 'member', 'override' or other token. D:\MinorApps\VetCompass\VetCompass\ViewModel\ViewModelBase.fs 18 7 VetCompass

Error 2 Incomplete structured construct at or before this point in pattern D:\MinorApps\VetCompass\VetCompass\ViewModel\ViewModelBase.fs 19 7 VetCompass

I'm not even sure where to begin with the indexer!

도움이 되었습니까?

해결책

All interface implementations are explicit, which means that the methods of the interface will be private when viewed as members of the class. Thus, you can't use the abstract and default modifiers in the implementation. Instead, you'll need to add a bit of duplication:

type ViewModelBase() =
    // declare a new virtual property
    abstract Error : string
    default this.Error = ""

    interface IDataErrorInfo with
       // pass through to the virtual property implementation
       member this.Error = this.Error

다른 팁

Object expressions can often be used in lieu of abstract classes and virtual methods. You can control behavior through arguments supplied to a "factory" function. Something like this:

type IMyInterface =
  abstract SayHello : unit -> string
  abstract Item : string -> obj with get

let makeMyInterface sayHello (lookup: IDictionary<string, obj>) =
  { new IMyInterface with
      member x.SayHello() = sayHello()
      member x.Item 
        with get name = lookup.[name] }

This probably won't work in your case, since you're constrained by the conventions of an existing framework. But it can be a nice alternative in some situations.

To implement IDataErrorInfo and INotifyPropertyChanged with a virtual implementation here is the code:

type ViewModelBase() =
    let propertyChangedEvent = new DelegateEvent<PropertyChangedEventHandler>()

    abstract Error : string with get
    default this.Error with get() = ""

    abstract Item : string -> string with get
    default this.Item with get(name) = ""

    interface INotifyPropertyChanged with
        [<CLIEvent>]
        member x.PropertyChanged = propertyChangedEvent.Publish
    member x.OnPropertyChanged propertyName = 
        propertyChangedEvent.Trigger([| x; new PropertyChangedEventArgs(propertyName) |])

    interface IDataErrorInfo with
       // pass through to the virtual property implementation
       member this.Error = this.Error
       member this.Item with get(x) = this.Item(x)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top