Tuesday 1 June 2010

C#: Policy based actions in C# using the Action delegate

I think it is not just me that, as a C# developer, sometimes I want that AOP feature so badly. Yes, a lot of AOP features can be simulated, but it's not that easy and mostly comes with a penalty of performance.

For example, I want to have some custom exception handling policy. It would be neat if I could simply decorate the method with an attribute as below.

[ExceptionHandlePolicy]
public void Method(){...}

To achieve this in C#:
  1. An attribute class implementing the IMessageSink is to be defined;
  2. The class, to which this attribute is going to be applied, must inherit from ContextBoundObject or MarshalByRefObject. 
Ehmmmm...all these are not easy changes to the existing code base, and the change to hook into the message sink will degrade the overall performance for sure.

The other way around, is to use the Action delegate from the .Net Framework to help to build a custom exception handling policy class.

public class RetryPolicy
{
    ...
    private Action _action;
    ...
 
    public RetryPolicy(Action action)
    {
        _action = action;
    }

    public void Execute()
    {
        int retryCount = 0;
        if(_action != null)
        {
            while(retryCount < MAX_RETRY)
            {
                try
                {
                    _action();
                    retryCount = MAX_RETRY;
                }
                catch(Exception ex)
                {
                   if(ShouldRetry(ex) && retryCount < MAX_RETRY)
                        i++;
                   else
                        throw;
                }
            }
        }
    }
    ....
}

To apply my custom retry policy, I can modify the existing data access layer slightly.

public static string GetConfigurationValue(string dbConnString, int configId)
{
    string configValue = string.Empty;
    RetryPolicy policy = new RetryPolicy( () =>
    {
        using(TestDAL dal = new TestDAL(dbConnString))
        {
            configValue = dal.GetConfigurationByValue(configId);
        }
    });

    policy.Execute();
    return configValue;
}

4 comments:

ilker said...

Is there a way to apply same thing for caching ? I mean AOP style.

Yan (Pamela) Yang said...

Yes, though the AOP style is achieved via message interception.

If it is a web method in a web service that you want to cache, you can annotate the method with the built-in attribute, such as:

[System.Web.Services.WebMethod(CacheDuration=60)]

ilker said...

Actually I have known that already. And it is possible with MVC as well as WebMethod. But need it for example data or business service libraries. Like PostSharp does. But without install something. (Team environment problems...)

Thanks for your answer BTW.

Kiquenet said...

Can I download all source code sample? thx