Code Snippets and Partial Methods by ThinqLinq

Code Snippets and Partial Methods

In my VB 9 language enhancements talks, I do them withalmost all coding on the fly as I find people often can comprehend the code. I start by building a quick class that is used throughout the demos. To assist, I do use the snippet functionality in VB. For example, if you type "property" and then tab twice, the designer will generate a private field with public property accessors. The if you change the highlighted values, any associated names will be changed as well.

Private newPropertyValue As String
Public Property NewProperty() As String
    Get
       
Return newPropertyValue
    End Get
    Set(ByVal value As String)
        newPropertyValue = value
    End Set
End Property

Personally, if you are not doing anything within your properties, there isn't much that you buy in using properties as compared to just exposing the field publically. I want a bit more functionality built into my properties. In the very least, I want to be able to include some change tracking. Once nice feature of the snippets is the fact that they are quite easy to modify and create your own.

To begin, we need to find where the supplied snippets are located on your disk. We can find this by clicking "Tools" and then  the "Code Snippets Manager". We can find the location by drilling into the "Code Patterns" then "Properties, Procedures, Events" and find the "Define a Property" snippet. The location window will show you where this one is located. In the default install, it will be in your c:\Program Files\Microsoft Visual Studio 9.0\Vb\Snippets\1033\common code patterns\properties and procedures\ folder. Navigate to this folder and copy the DefineAProperty.snippet. Paste it as a new file and name it whatever you want keeping the .snippet extension.

The snippet file is just a XML document. Open it with visual studio to edit it. The top is a Header which includes the description information that will show up in the snippet manager. One change you will need to make is to alter the "Shortcut" tag so that it will use the key combination you want to use to invoke your custom snippet. In my demos, I use "propertycc", thus I change the header as follows:

<Title>Define a Property with PropertyChanging</Title>
<
Author>Jim Wooley</Author>
<
Description>Defines a Property with a backing field.</Description>
<
Shortcut>Propertycc</Shortcut>

The key is to change the info in the Snippet node. In my case, I like to use a convention where the private field is the same name as the public property with the exception that it is prepended by the underscore. Thus, my field may be called _Foo and the property is called Foo. Due to this, I can eliminate the PrivateVariable node and just keep the PropertyName and PropertyType nodes.

With these changes in place, we can actually define our new generated code. This can be found in the CDATA section in the Code node. I use the following in my snippet declaration:

<![CDATA[Private _$PropertyName$ As $PropertyType$
Public Property $PropertyName$() As $PropertyType$
    Get
        Return _$PropertyName$
    End Get
    Set(ByVal value As $PropertyType$)
        If Not _$PropertyName$.Equals(value) Then
            _$PropertyName$ = value
            OnPropertyChanged("$PropertyName$")
        End If
    End Set
End Property
]]>

With this definition, any time we change the starting PropertyName, all associated values will be changed for each snippet. When we save our changed snippet and open a class libarry, we can start to use our new snippet by typing "propertycc" and the following code will be generated for us:

Private _NewProperty As String
Public Property NewProperty() As String
    Get
       
Return _NewProperty
    End Get
   
Set(ByVal value As String)
        If Not _NewProperty.Equals(value) Then
           
_NewProperty = value
            OnPropertyChanged("NewProperty")
        End If
   
End Set
End Property

Now our property has a detection as values change and we can then do something with it. In this case, we will call an OnPropertyChanged(propertyName as string) method, assuming we have defined one in our class. If we don't have one defined, we won't be able to compile our application. We have several options to provide the OnPropertyChanged method. The class could inherit from a base class implementtation. The additional complexity level may not necessary in many cases. Additionally, we could implement a concrete method in our class. This will mean a slight performance hit if we don't actually do anything in the method.

As an alternative, we can use the new partial methods in VS 2008. The great thing about partial methods is that if they are not implemented they are compiled away. Additionally, we can place the partial stub in a partial class for generated code and then put the implementing method in the other half of a partial class which is isolated to the custom business functionality. With this architecture in mind, we can define our partial method in the class with the rest of our generated code properties:

Partial Private Sub OnPropertyChanged(ByVal propertyName As String)

End Sub

In the other half of our partial class pair of files, we can implement the method as follows:

Private Sub OnPropertyChanged(ByVal propertyName As String)

RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(propertyName))

End Sub

Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

If we don't need the implementation, the OnPropertyChanged method call in the property setters will be compiled away, otherwise we already have the stubs in place with our snippet in order to handle the functionality as necessary.

If you are interested in trying out this snippet, I'm attaching it to this post. Simply unzip it to your snippets directory and try it out.

Posted on - Comment
Categories: VB) - VB Dev Center) -
comments powered by Disqus