Power4: Custom property templates and custom event templates

[This post is part of a series, "wish-list for future versions of VB"]

 

IDEA: Custom property templates. We should have an easy way for users to write boiler-plate code in their properties. This would include things like INotifyPropertyChanged, logging, validation. Here's how:

Class C

    Implements INotifyPropertyChanged

    Public Event PropertyChanged(s As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged

    Property Width As Integer From New MyProperty(0, 10, PropertyChangedEvent)

    Property Height As Integer From New MyProperty(0, 5, PropertyChangedEvent)

End Class

The "Property From ..." syntax means that this property should be implemented by the specified object, in this case a new instance of a class into which we put our boilerplate:

Class MyProperty

    Private notify As PropertyChangedEventHandler

    Private min, max As Integer

    Private _p As Integer

    Sub New(min As Integer, max As Integer, notify As PropertyChangedEventHandler)

        Me.min = min : Me.max = max : Me.notify = notify

    End Sub

    Public Function [Get]() As Integer

        Return _p

    End Function

    Public Sub [Set](value As Integer)

        If _p = value Then Return

        Dim propName = Reflection.GetCurrentMethod().Name.
Replace("set_", "").Replace("get_", "")

        If value < min OrElse value > max Then Throw New ArgumentOutOfRangeException(propName)

        _p = value

        Log("property " & propName & " changed to " & value)

        notify(Me, New PropertyChangedEventArgs(propName))

    End Sub

End Class

The compiler implements a simple getter which just calls into MyProperty.Get(), and a simple setter which just calls MyProperty.Set(value). The user can decide what kind of boilerplate code to put inside their custom property class, or what parameters to pass to its constructor. The "From" expression also allows you to provide any expression as the property template, e.g. a factory method, just so long as it returns a type on which the compiler can call Get() or Set(value). These Get/Set methods may even be extension methods.

 

SCENARIO: User has a lot of properties which all behave in pretty similar ways. It's tedious to have to write the same boilerplate code over and over again. It would be better to abstract the common behavior into a single place.

 

Note: This proposal lacks a handy way to specify what attributes should be placed on the property. For instance, we have to be able to say how the property should be serialized.

 

IDEA: Property tear-offs. We could obtain an object that represents a property, and lets you call its getter or setter explicitly:

        Dim w = AddressOf x.Width

   Dim i = w.Get()

        w.Set(i)

 

IDEA: Custom event templates. The same "custom property template" idea above could be applied to "custom event templates", where there is also a lot of boiler-plate code.

 

 

These ideas are only half-baked as yet. We recognize that there is tremendous user demand for custom property templates, but we don't think we've hit upon the best solution yet. Please, write back to say whether these ideas would accomodate the kinds of properties that you want. And if you have better ideas for custom property templates, please write with them.

Unanswered questions: would custom event templates help with WPF routed events? would joins in the style of "Concurrent Basic" be expressible using custom event templates?

There's also a big question: could all of this be better handled by the IDE?  Maybe we could use IDE projection-buffers, or "snippets on steroids". 

Finally, note that the trick to obtain "propName" from MethodBase.GetCurrentMethod is a bit ugly: it prevents inlining and requires you to put it inside the property itself. One idea here I'll blog about later today, "Power6: __CALLER_MEMBER__". It might be better to always pass the property's name as a string to the getter/setter, or somehow to the constructor.

 

Provisional evaluation from VB team: There's a decent idea lurking here, worth considering against the other ideas, but only if we're confident that we can design this one right.