benPearce
benPearce

Reputation: 38333

Auto implemented properties in C#

Is there a way to continue to utilise auto-implemented properties while still raising a change event, such as INotifyPropertyChanged, when Set is called?

Instead of:

private string _value;
public string Value
{
  get 
  { 
    return this._value;
  }
  set
  {
    this._value = value;
    this.ValueChanged(this,EventArgs.Empty);
  }
}

Can I just do:

public string Value 
{ 
   get; 
   set 
   { 
     this.ValueChanged(this,EventArgs.Empty); 
   }
}

Although the setter looks wrong, is it possible to do this without filling my class with backing-store variables?

UPDATE: Looks like there is no standard solution to my lazy objective, I think that the best solution is to use CodeRush or Resharper to generate all my backing stores for me.

Upvotes: 13

Views: 3949

Answers (8)

wimh
wimh

Reputation: 15232

The Fody add-in PropertyChanged does this. Just like KindOfMagic, Fody uses Mono.Cecil to modify the IL of .net assemblies at compile time. The following example is listed in the PropertyChanged documentation:

You write:

[ImplementPropertyChanged]
public class Person 
{        
    public string GivenNames { get; set; }
    public string FamilyName { get; set; }

    public string FullName
    {
        get
        {
            return string.Format("{0} {1}", GivenNames, FamilyName);
        }
    }
}

What gets compiled:

public class Person : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    string givenNames;
    public string GivenNames
    {
        get { return givenNames; }
        set
        {
            if (value != givenNames)
            {
                givenNames = value;
                OnPropertyChanged("GivenNames");
                OnPropertyChanged("FullName");
            }
        }
    }

    string familyName;
    public string FamilyName
    {
        get { return familyName; }
        set 
        {
            if (value != familyName)
            {
                familyName = value;
                OnPropertyChanged("FamilyName");
                OnPropertyChanged("FullName");
            }
        }
    }

    public string FullName
    {
        get
        {
            return string.Format("{0} {1}", GivenNames, FamilyName);
        }
    }

    public virtual void OnPropertyChanged(string propertyName)
    {
        var propertyChanged = PropertyChanged;
        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

The wiki includes some more advanced examples.

It is available using NuGet:

PM> Install-Package PropertyChanged.Fody

Upvotes: 0

benPearce
benPearce

Reputation: 38333

Since I asked this question this problem has actually been solved as an attribute and build task: https://github.com/demigor/kindofmagic

Upvotes: 1

Ali Shams
Ali Shams

Reputation: 11

This behavior can be done with a proxy factory type generator. I already done that in my development Framework. If you use System.Reflection.Emit you can create a type proxier. Consider below example:

var a = Proxier<InputType>.CreateInstance(new object[] { }); // object arrays are for different constructors
a.PropertyAccessed += ...

Upvotes: 0

gimalay
gimalay

Reputation: 493

You can use some AOP framework like PostSharp.

But it can reduce performance and build time.

Upvotes: 1

Timothy Walters
Timothy Walters

Reputation: 16874

This has been asked of the Microsoft team behind C# 3.0 and they did say they would think about it, have a read here.

In the comments you will find more information, including why it's a bad idea if you need more control, as well as ways to achieve it.

Upvotes: 1

womp
womp

Reputation: 116977

You can't do this. The specification for automatically implemented properties is pretty clear:

Automatically implemented (auto-implemented) properties automate this pattern. More specifically, non-abstract property declarations are allowed to have semicolon accessor bodies. Both accessors must be present and both must have semicolon bodies, but they can have different accessibility modifiers. When a property is specified like this, a backing field will automatically be generated for the property, and the accessors will be implemented to read from and write to that backing field. The name of the backing field is compiler generated and inaccessible to the user.

In other words, they can only have "get;" and "set;", with the possibility of access modifiers.

Upvotes: 6

Rob Windsor
Rob Windsor

Reputation: 6859

A quick Google search on "inotifypropertychanged auto properties" will lead you to several blog posts and articles on the subject. Here's one:

INotifyPropertyChanged auto wiring or how to get rid of redundant code

Upvotes: 4

Arsen Mkrtchyan
Arsen Mkrtchyan

Reputation: 50712

No you can't, because you don't have access to private field that generated for that property

Upvotes: 4

Related Questions