Advertisement
Advertisement


c# properties with repeated code


Question

I have a class with a bunch of properties that look like this:

public string Name
{
    get { return _name; }
    set { IsDirty = true; _name = value; }
}

It would be a lot easier if I could rely on C# 3.0 to generate the backing store for these, but is there any way to factor out the IsDirty=true; so that I can write my properties something like this and still get the same behaviour:

[MakesDirty]
public string Name { get; set; }
2008/09/15
1
5
9/15/2008 3:15:06 PM

Accepted Answer

No. Not without writing considerably more (arcane?) code than the original version (You'd have to use reflection to check for the attribute on the property and what not.. did I mention it being 'slower').. This is the kind of duplication I can live with.

MS has the same need for raising events when a property is changed. INotifyPropertyChanged that is a vital interface for change notifications. Every implementation I've seen yet does

set
{ 
  _name = value; 
  NotifyPropertyChanged("Name"); 
}

If it was possible, I'd figure those smart guys at MS would already have something like that in place..

2008/09/15
5
9/15/2008 2:55:11 PM


If you really want to go that way, to modify what the code does using an attribute, there are some ways to do it and they all are related to AOP (Aspect oriented programming). Check out PostSharp, which is an aftercompiler that can modify your code in a after compilation step. For example you could set up one custom attribute for your properties (or aspect, how it is called in AOP) that injects code inside property setters, that marks your objects as dirty. If you want some examples of how this is achieved you can check out their tutorials.

But be careful with AOP and because you can just as easily create more problems using it that you're trying to solve if not used right.

There are more AOP frameworks out there some using post compilation and some using method interception mechanisms that are present in .Net, the later have some performance drawbacks compared to the first.

2008/09/15

No, when you use automatic properties you don't have any control over the implementation. The best option is to use a templating tool, code snippets or create a private SetValue<T>(ref T backingField, T value) which encapsulates the setter logic.

private void SetValue<T>(ref T backingField, T value)
{
   if (backingField != value)
   {
      backingField = value;
      IsDirty = true;
   }
}

public string Name
{
   get
   {
      return _name;
   }
   set
   {
      SetValue(ref _name, value);
   }
}
2008/09/15

The other alternative might be a code generator such as codesmith to automate creating the properties. This would be especially useful if the properties you are creating are columns in a database table

2008/09/15

ContextBound object. If you create a class that extends context bound object and you create a ContextAttribute you can intercept the calls made to such a property and set the IsDirty. .NET will create a proxy to your class so all calls go over something like a remoting sink.

The problem with such an approach though is that your proxy will only be invoked when called externally. I'll give you an example.

class A
{
    [Foo]
    public int Property1{get; set;}
    public int Property2{get {return variable;} set{ Property1 = value; variable = value; }
}

When property1 is called from another class, your proxy would be invoked. But if another class calls property2, even though the set of property2 will call into property1 no proxy will be invoked, (a proxy isn't necessary when you're in the class itself).

There is a lot of sample code out there of using ContextBoundObjects, look into it.

2018/04/20

I'd say that the best way of solving this is to use Aspect-Oriented Programming (AOP). Mats Helander did a write up on this on InfoQ. The article is a bit messy, but it's possible to follow. There are a number of different products that does AOP in the .NET space, i recommend PostSharp.

2008/09/15

Source: https://stackoverflow.com/questions/63556
Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Email: [email protected]