Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing Func<> or similar to PostSharp aspect

Tags:

c#

.net

postsharp

In our external boundaries that expose WCF services, we convert all internal exceptions to FaultException. This is a manual process which often has minor flaws unique to each implementation. It has been copy/pasted and mindlessly modified (or forgotten) for each exposed method. To reduce the errors, I wanted to create an aspect which would catch any unhandled exception.

We do a mapping of internal exceptions to fault exceptions. How can I send a mapping function to the aspect?

If I add a property to the aspect like this:

[Serializable]
public sealed class FaultExceptionConverter : OnExceptionAspect {
    public Func<Exception, FaultException> FaultConverter { get; set }
}

I cannot (as expected by Attribute restrictions) initialize it like [FaultExceptionConverter(FaultConverter = MyConversionMethod)] (where MyConversionMethod is some method assignable to Func<Exception, FaultException>). Is there any pattern for passing this type of parameter to the aspect? Many types can be passed into aspects. Is this a common problem?

If there happens to be a better way to accomplish this, I would appreciate the advice.

like image 890
carlpett Avatar asked Nov 04 '22 08:11

carlpett


1 Answers

I've encountered similar frustrating limitations in aspect implementation, and one approach I've used to get around them is to have the aspect treat the class it is implemented on as some 'provider' type, which it can callback on to request other bits at runtime.

So, in your case, I imagine an OnException override that looks something like;

public override void OnException(MethodExecutionArgs args)
{
    IFaultConverterProvider provider = args.Instance as IFaultConverterProvider;
    if (null != provider)
        Func<Exception, FaultException>exceptionConverterFunc = provider.GetFunc();
}

Where IFaultConverterProvider is some interface you define and implement on the attributed type to provide the extra parameters you are missing.

Then, as a bit of a sanity check, you can introduce some compile-time validation into your aspect to ensure that the type it is applied to actually implements this required interface;

public override bool CompileTimeValidate(Type type)
{
    if (!type.IsImplementationOf(typeof(IFaultConverterProvider )))
    {
        // The aspect must be in a type which implements IFaultConverterProvider 
        Message.Write(
            MessageLocation.Of(type),
            SeverityType.Error,
            "CUSTOM02",
            "Cannot apply [MyFaultExceptionAspect] to type {0} because it does not implement IFaultConverterProvider .", type);
            return false;
    }

    return true;
}
like image 145
RJ Lohan Avatar answered Nov 15 '22 06:11

RJ Lohan