What kind of compiler magic do we need more?

I develop lot view models which are:

1) All have to implement INotifyPropertyChanged to be bindable to UI.

2) Property setters have to raise PropertyChanged on change.

3) PropertyChanged event has to provide proper property name.

If you (like me) tied of writing something like this:

public string Name 
{
  get 
  { 
    return _name; 
  }
  set 
  { 
    if (_name != value) 
    {
      _name = value;
      RaisePropertyChanged("Name");
    }
  }
} 

Then refactor this method like this and sometimes forget to update property name literal:

string _fundName;
public string FundName 
{
  get 
  { 
    return _fundName; 
  }
  set 
  { 
    if (_fundName != value) 
    {
      _fundName = value;
      RaisePropertyChanged("Name");
    }
  }
} 

And then spend a day to debug why your UI is not refreshing and databinding doesn't work properly.

Then all we need is some kind of magic.

What if I just need to write this:

[Magic] // implicit transformation
public string FundName { get; set; }

or if I have many properties:

[Magic]
public class MyViewModel
{
  public string FundName { get; set; }
  public string FundType { get; set; }

  [NoMagic] // suppress transformation
  public int InternalId { get; set; }
}

So I have just developed a MSBuild task to do this magic after the build (http://kindofmagic.codeplex.com).

The question is, what kind of magical postprocessing would you like more?

Does automatic implementation of INotifyPropertyChanging makes sense?

Answers


If we're going to have fancy code generation, I think I would prefer a way to generate DependancyProperties more easily. The snippit I use is certainly helpful, but I'm not a fan how jumbled the code looks when you have on-changed and coerce callbacks, and metadata options. Maybe I'll try and mock up a sample after work.

Edit: Well, here's one concept. It would look a lot more clever if you pass anonymous methods to attributes, but it's still a step up.

Before:

[DpDefault("The Void")]
[DpCoerce(new CoerceValueCallback(MainWindow.CoerceAddress))]
[DpChanged(new PropertyChangedCallback(MainWindow.ChangeAddress1))]
[DpChanged(new PropertyChangedCallback(MainWindow.ChangeAddress2))]
[DpOptions(FrameworkPropertyMetadataOptions.Inherits)]
public string Address {
    get { return Dp.Get<string>(); }
    set {
        if (Dp.Get<string>() != value) {
            Dp.Set(value);
            PostOffice.SendMailToTheBoss("I moved!");
        }
    }
}

After:

public string Address {
    get { return (string)GetValue(AddressProperty); }
    set {
        if ((string)GetValue(AddressProperty) != value) {
            SetValue(AddressProperty, value);
            PostOffice.SendMailToTheBoss("I moved!");
        }
    }
}

public static readonly DependencyProperty AddressProperty =
    DependencyProperty.Register("Address", typeof(string), typeof(MainWindow),
        new FrameworkPropertyMetadata((string)"The Void",
            FrameworkPropertyMetadataOptions.Inherits,
            new PropertyChangedCallback(MainWindow.ChangeAddress1)
                + new PropertyChangedCallback(MainWindow.ChangeAddress2),
            new CoerceValueCallback(MainWindow.CoerceAddress)));

Typically, only the 'DpDefault' attribute would be used, but even if it doesn't make the code shorter, it certainly makes it clearer. Here would be a more typical example:

Before:

[DpDefault("The Void")]
public string Address { get; set; }

After:

public string Address {
    get { return (string)GetValue(AddressProperty); }
    set { SetValue(AddressProperty, value); }
}

public static readonly DependencyProperty AddressProperty =
    DependencyProperty.Register("Address", typeof(string), typeof(MainWindow),
        new UIPropertyMetadata((string)"The Void"));

Try this

http://code.google.com/p/notifypropertyweaver/

  • No attributes required
  • No references required
  • No base class required

Here is my blog article about it

http://codesimonsays.blogspot.com/2010/11/attempting-to-solve-inotifypropertychan.html

It supports the attributes you request

  • NotifyPropertyAttribute (notify for a property)
  • NotifyForAllAttribute (notify for all properties on a type)
  • NotifyIgnoreAttribute (do not notify for a property or type)
  • AlsoNotifyFor (Allows the injection of notify code that points to a different property)

Although these are option and designed for fine tuning. Most injection is done by convention through analyzing the existing IL.


"Magic" is almost always a terrible name for method or property or variable in any language. You should rename the attribute to something more descriptive. Imagine you are just a random internet pedestrian and stumble on a piece code with attribute "Magic", what does it tell you about the code? Exactly nothing :)

I will try your code anyways, it has potential to be quite a timesaver. This should definitely be a part of .NET.


Need Your Help

$_SERVER over time()

php

What I stumbled upon seems pretty interesting and awakened my curiosity. I read in a micro optimization article that it would be smart to use the anyway present $_SERVER['REQUEST_TIME'] instead of

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.