Adding AOP to Staff Intranet

Because I’m a stickler for good code I put exception handling into my task layer and wrap any exception that may be raised from the data access layer into an appropriate exception for the task layer and also log the exception, because of this I end up having lots of unit test code that looks similar to make sure I’m enforcing this rule:

[Test]
public void Should_log_exception_if_exception_is_raised_when_deleting_session()
{
    Guid id = Guid.Empty;
    IAdministrationRepository mockRepository = CreateMock();

    IServiceResolver mockResolver = CreateMock();
    ILog mockLog = CreateMock();
    Exception mockException = new Exception( "mock ex" );

    using (Record)
    {
        SetupResult.For(mockResolver.Resolve())
                   .Return(mockLog);
        SetupResult.For(mockRepository.FindLoginSessionBy(id))
                   .IgnoreArguments()
                   .Return(new LoginSession(id));
        mockRepository.Delete(null);
        LastCall.IgnoreArguments()
                .Throw(mockException);
        mockLog.Error(mockException);
    }

    using (PlayBack)
    {
        try
        {
            IoC.InitializeWith(mockResolver);
            IAuthenticationTask sut = createSUT(mockRepository);
            sut.InvalidateSessionFor(id);
        }
        catch { }
    }
}

And to fulfill this I then end up with cross cutting code to meet the test behaviour:

try
{
    //... work here
}
catch (Exception thrownException)
{
    Log(thrownException);
    throw new ProblemSavingStaffMemberException(thrownException);
}

To try and cut down on this cross cutting code and to keep the tasks more lean I did some investigation into some AOP strategies.

My first reaction was… I’m using Castle Windsor so can I utilize it’s built in AOP capabilities after changing some code and adding an interceptor I quickly found out this won’t be possible as it doesn’t support out or ref parameters and due to some of my task layer method using out parameters to pass back a notification object this choice was gone!

Next up I had a look at PostSharp the difference between them being that PostSharp adds code in after compilation whereas Windsor dynamically creates proxies at runtime. After looking at some examples I had an idea as to how to implement it so after installing PostSharp I created my object that will inject itself into other objects:

[Serializable]
[AttributeUsage(AttributeTargets.All)]
public class TaskExceptionHandlerAttribute : OnMethodBoundaryAspect
{
    public override void OnException(MethodExecutionEventArgs eventArgs)
    {
        Exception thrownException = eventArgs.Exception;
        LogException(thrownException);
        WrapExceptionWithAttribute wrapExceptionAttribute = RetrieveWrappingExceptionAttribute(eventArgs.Method);
        if (wrapExceptionAttribute != null)
        {
            Type exceptionToWrapWith = wrapExceptionAttribute.WrapExceptionType;
            Exception exceptionToThrow = (Exception)Activator.CreateInstance(exceptionToWrapWith, thrownException);
            if (exceptionToThrow != null)
                throw exceptionToThrow;
        }
        throw new TaskLayerException(thrownException);
    }

    private static WrapExceptionWithAttribute RetrieveWrappingExceptionAttribute(MethodBase method)
    {
        WrapExceptionWithAttribute wrapExceptionAttribute =
        method.GetFirstCustomAttribute(typeof(WrapExceptionWithAttribute),false);
        return wrapExceptionAttribute;
    }

    private static void LogException(Exception thrownException)
    {
        ILog log = IoC.Resolve();
        log.Error(thrownException);
    }
}

In order to not have to place this object as an attribute on all the different task classes I can use the assembly attribute and give it a target using a name plus a wildcard:

[assembly: TaskExceptionHandler(AttributeTargetTypes="MCromwell.StaffIntranet.Task.Tasks.*")]

And that’s it my methods are now injected with the PostSharp code after compilation to handle exceptions and at which point it will call my custom code very cool!

One thing you may have noticed is the use of another attribute that can be decorated on the task methods WrapExceptionWithAttribute this attribute takes a Type in it’s constructor this Type is the exception that should wrap the thrown exception ideally we would like this attribute to be placed on all public task class methods so that we raise applicable exceptions depending on the task be performed although how do we enforce this convention?…

In my next post I will be demonstrating a technique that allows to enforce these types of conventions we want for our systems.

Advertisements

Writing your own Provider

Writing the Provider base class

Providers need to have a base class they can inherit from to provide the necessary functionality for example:

public abstract class MenuProviderBase : ProviderBase
{
    public abstract IEnumerable RetrieveMenuItems();
}

This base class should inherit from the ProviderBase class in the System.Configuration assembly, by convention it should be marked as abstract.

Custom provider collection class

You also need to create a provider collection class this will hold a collection of your custom providers:

public class MenuProviderCollection : ProviderCollection
{
    public new MenuProviderBase this[string name]
    {
        get {return base[name] as MenuProviderBase;}
        set {base[name] = value;}
    }

    public override Add(ProviderBase provider)
    {
        if (provider == null)
            throw new ArgumentNullException("provider");

        if (provider as MenuProviderBase)
             throw new ProviderException("Invalid provider type");

             base.Add(provider);
    }
}

Writing the configuration section class

 You need to have a way to translate the settings from the web.config file into an object that knows how to handle them, this is acheived by inheriting from the ConfigurationSection class:

public class MenuProviderConfigurationSection : ConfigurationSection
{
    [ConfigurationProperty("defaultProvider")]
    public string DefaultProvider
    {
        get {return base["defaultProvider"] as string;}
        set {base["defaultProvider"] = value;}
    }

    [ConfigurationProperty("providers")]
    public ProviderSettingsCollection Providers
    {
        get {return base["providers"] as ProviderSettingsCollection;}
    }
}

Using the ProviderConfigurationCollection allows us to rely on the built-in provider model to handle passing configuration values to our providers as you will see later on.

Writing a provider implementation

With the provider base class in place we can create our own custom provider implementation:

public class XmlMenuProvider : MenuProviderBase
{
    private string xmlFile = string.Empty;
    private string name = "XmlMenuProvider";
    public override Initialize(string name, NameValueCollection config)
    {
        if (!string.IsNullOrEmpty(name))
            this.name = name;

        this.xmlFile = config["xmlFile"];

        if (string.IsNullOrEmpty(xmlFile))
            throw new ProviderException("xmlFile attribute must be supplied");
    }

    public override IEnumerable RetrieveMenuItems()
    {
        //... read xml file populate, perform some yield returns on matched nodes
    }
}

As I mentioned before by using the ProviderConfigurationCollection we get any attributes declared for the provider pushed into the Initialize method via the config NameValueCollection parameter pretty neat, you still need to make sure that the necessary settings have been placed in the config file like I’m doing for the xmlFile setting above.

Creating a provider factory

in order to get hold of a provider implementation we need somewhere where we can look at the config, grab the appropiate configuration section we declared above, instantiate the providers and pull out the one to use, this is something that we don’t want to perform everytime we ask for a provider so instead we use a factory that should only do this operation once and for subsequent calls it will give us a provider already instantiated, here’s the code:

public static class MenuProviderFactory
{
    private static MenuProviderBase activeProvider = null;
    private static MenuProviderCollection providers = null;
    private static readonly object locker = new object();

    public static MenuProviderBase RetrieveMenuProvider()
    {
        if (activeProvider == null)
        {
            lock (locker)
            {
                if (activeProvider == null)
                {
                    MenuProviderConfigurationSection config =
                                                                                 WebConfigurationManager.GetSection( "system.web/menuProviders" ) as MenuProviderConfigurationSection;

                    if (config == null)
                        throw new ConfigurationErrorsException("menuProviders section is not a MenuProviderConfigurationSection" );

                    providers = new MenuProviderCollection();
                    ProvidersHelper.InstantiateProviders(config.Providers, providers, typeof(MenuProviderBase));
                    activeProvider = providers[config.DefaultProvider);
                    if (activeProvider == null)
                        throw new ProviderException("unable to load default provider");
                }
            }
        }

        return activeProvider;
    }
}

We can utilize some of the classes found in the System.Web.Configuration namepsace, namely the WebConfigurationManager which can provider us our particular section by supplying it with the path location. Also we can use the ProvidersHelper class to instantiate the providers by passing in the provider settings from our configuration section.

Setting up web.config

After we have all the classes in place we then need to configure the web.config, firstly we need to add a section to the system.web sectionGroup, so inside the configuration element add the following:


    <section />

After adding that we then need to add the actual provider section, so inside the system.web element add the following:


    
        
    

Usage

For this example we will assume we have our own menu control, the usage inside the Render method becomes:

public void Render(HtmlTextWriter writer)
{
    MenuProviderBase provider = MenuProviderFactory.RetrieveMenuProvider();
    foreach (MenuItem menuItem in provider.RetrieveMenuItems())
    {
        //... create html elements for screen
    }
}

First codeproject article posted

I just finished posting my first article to codeproject (only taken 3 years since I joined!), it covers unit testing against a database and also provides a handy little testing library that can be used to make it a little easier you can check it out at http://www.codeproject.com/KB/cs/unittestingdblib.aspx

VB.Net Gotcha using ByRef

C# will not let you compile if you try an pass a property or a readonly field as a ref argument to a method:

you will get:

A readonly field cannot be passed ref or out (except in a constructor)

or

A property or indexer may not be passed as an out or ref parameter

This is good it protects from doing something silly, however VB.NET does not have this compile checking and instead will let the following compile without even a warning:

Public Class AnotherTestClass
    Private _number As Integer

    Public ReadOnly Property Number() As Integer
        Get
            Return _number
        End Get
    End Property

    Public Sub ChangeMyNumber()
        TestClass.ChangeNumber(Number)
    End Sub

End Class

When the ChangeNumber method on the TestClass uses byref for the integer passed in:

Public Shared Sub ChangeNumber(byRef output)
    output = 1
End Sub

When the above is executed the Number property remains the same as before the method call. This was tested in VS2005, at first i thought it was a VS2003 only issue.