views:

1141

answers:

10

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; }
+3  A: 

You could try setting up a code snippet to make it easy to create those.

Joel Coehoorn
A: 

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

LepardUK
A: 

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 isnt necessary when youre in the class itself).

Theres a lot of sample code out there of using contextboundobjects, look into it.

Amir, this technically is a solution - however personally don't think this to be a good place to apply this :) Good answer - however can't upvote it in the context of this question. Sorry for the pun too :)
Gishu
+4  A: 

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..

Gishu
A: 

I can recommend to use Enterprise Library for that purpose. Policy Application Block delivers the infrastructure to do "something" (something = you can code that on your own) whenever you enter/exit a method for example. You can control the behavior with attributes. Take that as a hint an go into detail with the documentation of enterprise library.

JRoppert
A: 

There's a DefaultValueAttribute that can be assigned to a property, this is mainly used by the designer tools so they can indicate when a property has been changed, but, it might be a "tidy" way of describing what the default value for a property is, and thus being able to identify if it's changed.

You'd need to use Reflection to identify property changes - which isn't actually that expensive unless you're doing lots of it!

Caveat: You wouldn't be able to tell if a property had been changed BACK from a non-default value to the default one.

Rob
+1  A: 

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);
   }
}
Scott Dorman
But then you'd have to duplicate the SetValue<T> method in every such class. If you turn it into a public static/utility method, you'd have to expose the IsDirty state.. Not cool :)
Gishu
@Gishu: Yes, you would duplicate the call to SetValue in each property and possibly in each class. Depending on how your calsses are derived will determine if SetValue (and consequently IsDirty) are public.
Scott Dorman
A: 

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.

Thomas Lundström
A: 

If you do go with Attributes, I'm fairly certain you'll have to roll your own logic to deduce what they mean and what to do about them. Whatever is using your custom class objects will have to have a way of performing these attribute actions/checks, preferably at instantiation.

Otherwise, you're looking at using maybe events. You'd still have to add the event to every set method, but the benefit there would be you're not hard-coding what to do about dirty sets on every property and can control, in one place, what is to be done. That would, at the very least, introduce a bit more code re-use.

Yadyn
+2  A: 

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.

Pop Catalin