2

Let's say I have an attribute class:

public class MyCustomAttribute : Attribute
{
    // do stuff
}

And I use this attribute on class properties:

public class MyModel : BaseModel
{
    [MyCustom]
    public string Name { get; set; }
}

Is there a way, within the code of MyCustomAttribute, to reference the instance of MyModel on which it's being used?

Ultimately I'm just experimenting with AOP (using PostSharp) to create attributes to track when a model is dirty. So if BaseModel has an IsDirty property then I'd like to be able to do something like this with PostSharp:

public class TrackDirtyPropertyAttribute : OnMethodBoundaryAspect
{
    public override void OnSuccess(MethodExecutionArgs args)
    {
        someReferenceToTheObject.IsDirty = true;
    }
}

I've tried passing a reference into the attribute's constructor:

public class TrackDirtyPropertyAttribute : OnMethodBoundaryAspect
{
    private BaseModel _currentObject { get; set; }

    public TrackDirtyPropertyAttribute(BaseModel currentObject)
    {
        _currentObject = currentObject;
    }

    public override void OnSuccess(MethodExecutionArgs args)
    {
        _currentObject.IsDirty = true;
    }
}

However, when I use it:

[TrackDirtyProperty(this)]
public string Name { get; set; }

It tells me that this is not available in that context.

David
  • 208,112
  • 36
  • 198
  • 279

2 Answers2

4

You should do it like this:

public class TrackDirtyPropertyAttribute : OnMethodBoundaryAspect 
{ 
    public override void OnSuccess(MethodExecutionArgs args) 
    { 
        ((BaseModel) args.Instance).IsDirty = true; 
    } 
} 
Gael Fraiteur
  • 6,759
  • 2
  • 24
  • 31
2

Your constructor won't work (at least not with this) because the attribute constructor arguments must be accessible in a static context. And by default you can't simply access the utilising type's instance - which makes sense, since this is essentially metadata (applied to the definition, not instances - the instances just come 'strapped' with it). So you can natively access the attributes of a type, but not the instances of the type used by an attribute.

You could probably get it through some contrived reflection and so forth (I'm not even going to venture into thinking about this), however, not so elegantly one way as the other.

On another note, it makes little sense to me to store the state of an element within an attribute - this isn't persistent enough. Making calculations to retrieve a value (say you did get a hold of the instance, and managed to run some logic to determine if it 'is dirty' and provide a 'real time' value in that sense) yes, but using it to persist information applied to it after the fact of declaration seems futile, since which instance of the attribute is it to persist in anyway? In any case, and regardless of what I might have totally missed in saying this, this is what the instances themselves are for.

Grant Thomas
  • 44,454
  • 10
  • 85
  • 129