Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391396

PostSharp aspect for property setters, calling generic method

We have a base object we use for some MVC-like system, where each property in a descendant is written like this:

public String FirstName
{
    get { return GetProperty<String>("FirstName", ref _FirstName); }
    set { SetProperty<String>("FirstName", ref _FirstName, value); }
}

This is done both for debugging purposes and for notification and validation purposes. We use the getter to alert us of cases where code that has explicitly flagged what it is going to read (in order for the base class to be able to call it only when those properties change) and gets it wrong, and we use the setter for property change notifications, dirty-flag handling, validation, etc.

For simplicity, let's assume the implementation of these methods looks like this:

protected T GetProperty<T>(String propertyName,
    ref T backingField)
{
    return backingField;
}

protected Boolean SetProperty<T>(String propertyName,
    ref T backingField,
    T newValue)
{
    backingField = newValue;
    return true;
}

There's more code in both of these of course, but this code is not relevant to my question, or at least I hope so. If it is, I'll modify the question.

Anyway, I'd like to write a PostSharp aspect that automatically implements the calls for me, on automatic properties, like this:

public String FirstName { get; set; }

Is there anyone out there that has some idea how I would go about doing this?

I have made OnMethodBoundaryAspect classes myself, but the art of calling the generic implementation with a ref parameter eludes me.

Here's the two classes, I'd like to augment the TestObject class to automatically call the correct method on property get and set.

public class BaseObject
{
    protected T GetProperty<T>(String propertyName,
        ref T backingField)
    {
        return backingField;
    }

    protected Boolean SetProperty<T>(String propertyName,
        ref T backingField,
        T newValue)
    {
        backingField = newValue;
    }
}

public class TestObject : BaseObject
{
    public String FirstName
    {
        get;
        set;
    }

    public String LastName
    {
        get;
        set;
    }
}

Edit: Posted on PostSharp forum as well.

Upvotes: 2

Views: 2631

Answers (1)

Brian Adams
Brian Adams

Reputation: 996

It should be very simple. You override the OnEntry and set the return value based on your own code. At the end you use:

eventArgs.ReturnValue = GetValue(x,y);  
eventArgs.FlowBehavior = FlowBehavior.Return;

which will effectively intercept the original Get/Set calls.

Refer to this blog which shows the cache aspect using the same pattern...

Upvotes: 2

Related Questions