tags:

views:

358

answers:

7

The language shortcut

public string Code
{
    get;
    set;
}

saves a bit of typing when defining trivial properties in C#.

However, I find myself writing highly repetitive, not-quite-as-trivial property code that still follows a clear pattern e.g.

public string Code
{
    get { return code; }
    set 
    {
        if (code != value)
        {
            code = value; 
            NotifyPropertyChanged("Code");
        }
    }
}

I can certainly define a Visual Studio snippet to reduce typing. However, if I need to add something to my pattern, I have to go back and change quite a bit of existing code.

Is there a more elegant approach? Is a snippet the best way to go?

UPDATE:

As a quick improvement for right now, I have edited (after making a backup)

C:\Program Files\Microsoft Visual Studio 10.0\VC#\Snippets\1033\Refactoring\EncapsulateField.snippet

(path is for VS 2010)

to reflect my current pattern. Now, the built-in refactoring tool uses my template to create a property from a field. Drawbacks: Global change for Visual Studio, cannot retroactively change existing property code.

A: 

a very common pattern. Snippet is ok, but boy, wouldn't it be great if MS created some syntactical sugar for auto property change notifications....

Something like....

public string Code { get; setwithnotify; }

That would indeed be very nice.

Tim Jarvis
@Tim: Yes that would handle this particular pattern, though still leaves the general problem of repeating some arbitrary pattern - ideally with the ability to insert modifications for a given property - unsolved.
Eric J.
+2  A: 

I haven't done it myself, but I have seen a dependency injection framework be used for this particular task.

Goes and Googles

Ahaha!

It seems, using the Unity DI framework, you can inject the INotifyPropertyChanged into the automatic property. Have a look at this great blog post: http://shecht.wordpress.com/2009/12/12/inotifypropertychanged-with-unity-interception-aop/

This reminds me of a recent HanselMinutes, where Scott is talking to a guy about Aspect Oriented Programming (AOP) where this type of injection is very common place.

Alastair Pitts
@Alastair: DI looks very promising. Though not stated in the question, I'm working with Silverlight at the moment. Wonder if Unity 2.0 for Silverlight also supports that pattern (don't know what they had to leave out vs. the standard edition).
Eric J.
+1  A: 

I hate writing that code!

In the past, to deal with this problem, I have implemented a code generator to produce a partial class with the property definitions.

Jay Bazuzi
@Jay: I have done code generation from UML models in the past myself. That's a great approach when the project is "large enough" to warrant a model-based approach and creation of the code generator. With modeling tools getting more and more powerful/integrated, the "large enough" threshold keeps coming down.
Eric J.
@Eric: Personally, I would avoid UML and all its intellectual overhead. I think your goal here is simple: classes with properties that notify on changed. A simple solution might be a PowerShell script that lets you write: `class C { property string Code; }` and produces a partial class. I've done this before when I also wanted a fluent interface to the class.
Jay Bazuzi
+2  A: 

Here is something I mocked up as an exercise. Originally inspired by Jon Skeet's blog post.

public static class ObjectExtensions {
    public static string GetPropertyNameAndValue<T>(this T obj, out object value) {
        System.Reflection.PropertyInfo[] objGetTypeGetProperties = obj.GetType().GetProperties();
        if(objGetTypeGetProperties.Length == 1) {
            value = objGetTypeGetProperties[0].GetValue(obj, null);
            return objGetTypeGetProperties[0].Name;
        } else
            throw new ArgumentException("object must contain one property");
    }
}

class Whatever {
 protected void ChangeProperty<T>(object property, T newValue, Action change) {
     object value;
     var name = property.GetPropertyNameAndValue(out value);

     if(value == null && newValue != null || value != null && !value.Equals(newValue)) {
         change();
         OnPropertyChanged(name);
     }
 }

 private string m_Title;
 public string Title {
     get { return m_Title; }
     set {ChangeProperty(
               new { Title }, //This is used to dynamically retrieve the property name and value
               value, // new value
               () => m_Title = value); //lambda to change the value 
     }
 }
}

This is the best I could come up with. The runtime performance hit could be pretty high, but I haven't tested it.

A bit of explanation on the above solution. new { Title } creates an anonymous object and due to projecttion (introduced in .NET 3.5) the newly created object has a single property called Title and the value which is the value of Title property of the original object.

GetPropertyNameAndValue is the function that does all the interesting work - it retrieves the name and the value of the property out of the anonymous object. ChangeProperty then performs equality check and invokes the lambda that actually changes the property and also calls NotifyPropertyChanged.

Alternatively you could just do a snippet like so:

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"&gt;
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>propfullinotify</Title>
            <Shortcut>propfullinotify</Shortcut>
            <Description>Code snippet for property and backing field with INotifyPropertyChanged</Description>
            <Author>Microsoft Corporation</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>type</ID>
                    <ToolTip>Property type</ToolTip>
                    <Default>int</Default>
                </Literal>
                <Literal>
                    <ID>property</ID>
                    <ToolTip>Property name</ToolTip>
                    <Default>MyProperty</Default>
                </Literal>
                <Literal>
                    <ID>field</ID>
                    <ToolTip>The variable backing this property</ToolTip>
                    <Default>myVar</Default>
                </Literal>
            </Declarations>
            <Code Language="csharp">
      <![CDATA[private $type$ $field$;

    public $type$ $property$
    {
        get { return $field$;}
        set {
      if ($field$ != value)
      {
        $field$ = value;
        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("$property$"));
      }
    }
    }
    $end$]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>
Igor Zevaka
@Igor: That's an interesting approach to use extension methods, though I don't fully follow the implementation. What does the part "new { Title }, title" do? Why isn't "value" referenced?
Eric J.
Hehe, its actually something Jon Skeet came up with way back when, and is a way to get the name of the property at runtime. `value` not being referenced is actually a bug, due to lifting it out from somewhere else. I ll fix it up and expand on the solution.
Igor Zevaka
@Igor: Thanks for the clarification. Certainly an interesting approach!
Eric J.
A: 

To answer the general question about repetetive code, not just the property change notification case:

Sure. This is a perfect case for a macro.

Oh wait. C# doesn't have macros. Because of course, macros are evil and aren't the best solution for any programming problem.

Unless you insert a preprocessor into your build.

Conrad Albrecht
-1: Not helpful.
Cameron MacFarland
Not helpful (and wouldn't even be a good suggestion if the question was in c++)
Rune FS
+1  A: 

This is know as Aspect Oriented Programming (AOP).

Scott Hanselman recently did an interview with the creator of LinFu, Philip Laureano on this topic. (link)

There are a number of AOP tools out there, depending on your needs.

And finally, some implementations of an INotifyPropertyChanged class using the above tools:

Cameron MacFarland
+1 Easily the best and most appropriate answer!
Pat
A: 

Thank everyone for your responses. I have upvoted the useful answers. However, after quite a bit of research I have come to believe that the best answer (at least for me and the way I develop software) is to model the classes in Visual Studio and use T4 to code-generate partial classes that implement the property code.

See http://msdn.microsoft.com/en-us/library/ee329480.aspx

Eric J.