f#类型提供程序和INPC元编程

时间:2012-12-09 10:20:22

标签: f# inotifypropertychanged type-providers

我阅读了以下文章

http://studentguru.gr/b/kron/archive/2012/09/26/c-template-metaprogramming-and-f-type-providers.aspx

显示了使用F#Type提供程序生成编译时Fibonacci序列的方法。解决方案在文章中,但最终的程序是

> cat .\fib.fs
type fib = Playground.StaticFibonacci<100000>
printfn "Fibonacci(100000) has %d digits" fib.Value.Length
> fsc .\fib.fs -o fib.exe -r:.\FibonacciTypeProvider.dll –nologo
> .\fib.exe
Fibonacci(100000) has 20899 digits

这看起来非常强大。我想知道是否有可能为INPC(INotifyPropertyChanged)创建一个类型提供程序,这样你就可以代替

open System.ComponentModel

type MyObject() =
    let mutable propval = 0.0

    let propertyChanged = Event<_, _>()
    interface INotifyPropertyChanged with
        [<clievent>]
        member x.PropertyChanged = propertyChanged.Publish

    member this.MyProperty
        with get() = propval
        and  set(v) =
            propval <- v
            propertyChanged.Trigger(this, new PropertyChangedEventArgs("MyProperty"))

您可以写

open System.ComponentModel

type MyObject() =
    let mutable propval = 0.0

    let propertyChanged = Event<_, _>()
    interface INotifyPropertyChanged with
        [<clievent>]
        member x.PropertyChanged = propertyChanged.Publish

    member this.MyProperty : INPCTypeProvider<double>

所以在我浪费半天之前深入研究这个问题或许更有信息的人可能会告诉我,我在浪费时间,这种级别的元编程是不可能的。

1 个答案:

答案 0 :(得分:6)

我认为你不能用F#类型的提供者实现这一点(但我可以看到它会很好)。我能想到很多问题和想法:

  • 在您的示例中,您的INPCTypeProvider<double>必须返回类似“属性”的表示形式。这是不可能的,因为属性不是一等值(与事件不同)。如果是,您将不需要类型提供者......

  • 类型提供程序无法通过现有类型进行参数化,因此您无法编写说:

    type MyNotifyObject = ProvideNotifiable<MyObject>
    

    如果可能,ProvideNotifiable可以是提供类型并使用其他接口实现构建新类型的提供者。但目前这是不可能的。

  • 如果您只需要简单的类型,您可以创建类似的内容:

    type MyObject = ProvideNotifiable<"MyProperty:int, OtherProperty:string">
    

    这可以生成具有两个属性(在字符串中定义)的类型,但是您不能向生成的类型添加任何其他内容(尽管您可以使用生成提供程序生成实际类型并继承它...)我认为这可能是你能做的最好的。

除了类型提供程序之外,您还可以通过引用简化INotifyPropertyChanged的实现。这个F# snippet gives a simple example使实施更加安全。