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.