Advice on AOP with C# [closed]

2019-04-21 05:50发布

问题:

I have an ASP.NET 3.5 SP1 Webforms Application. I use the MVP pattern (supervising controller) with DI (autofac). My presenters call to the repository contracts defined in my Domain (DDD) which are implemented in an Infrastructure project.

The repository methods the presenters call can hork, so I need to log exceptions and then set an error message on the View.

In the past I would have added another parameter to the Presenter constructors, stored the reference in a Base Presenter, and called a Log method in my Catch blocks. I don't really like this, but it gets the job done.

I could go the route of using a factory to get the logging class as described here, but I'd like to explore AOP first, as it seems pretty interesting.

I have done the reading on compile-time vs runtime AOP, and I'd like to know what peoples' experiences are with the different solutions, pluses, minuses, words of advice, etc.

From the digging I have done it seems like there are 4 main frameworks for AOP in .NET

  • Castle Windsor - I have stayed away from this in general because it does a whole lot of stuff I really don't need
  • Spring.net - sounds like it has a good track record but inspires fear through its xml configuration (I don't like non-fluent configurations)
  • PostSharp - Attribute driven (I like this) but at one point had some line number issues, not sure if they still exist
  • Unity - a whole lot of stuff I don't really need

I see another question that has some good answers but its from a year and a half ago. Are there newer, "better", frameworks that have been developed in the meantime, or enhancements made to existing solutions that should be taken into consideration?

For reference, I chose Autofac for DI because its fluent, simple to use, couldn't find any negative comments about it, and it just works.

Are there recommendations on which AOP framework I should try? Thanks for reading all of this and for adding any thoughts.

回答1:

Short answer, for simplicity and ease of use, you really can't go wrong with PostSharp.

Longer answer: In my mind, you should choose between the two frameworks depending on what you are trying to achieve.

If you want aspects that should change based upon context, consider Spring.NET (or any aop framework that injects code at runtime based on configuration). This allows you to customise the behaviour of your objects depending on what you are doing. For example, via your configuration, you may use one type of logging in a console app, and another in a web app. Note that Spring is also a DI container (and several other things) -- it goes well beyond AOP, and it is definitely worth learning how to use.

On the other hand, if you want behaviour that should always be in effect, regardless of context, then PostSharp (compile time weaving) is your best bet. This is effectively the same as if you include the code in each method you apply the aspect to.

For what you're doing, I recommend you start with PostSharp.



回答2:

For simple aspect scenarios, I'd pass the method body as a block to a generic method that handles the aspect, i.e. implementing the «hole in the middle» design pattern.

Example:

public class Class
{
    public void MethodWithoutAspect()
    {
        var dummy = new string('a', 10);

        Console.WriteLine(dummy);
    }

    public void MethodWithAspect()
    {
        Aspect.LogException(() =>
        {
            var dummy = new string('a', 10);

            Console.WriteLine(dummy);
        });
    }
}

public static class Aspect
{
    public static void LogException(Action block)
    {
        try
        {
           block();
        }
        catch (Exception e)
        {
            Log(e);
            throw;
        }
    }

    private static void Log(Exception e)
    {
        throw new NotImplementedException();
    }
}


回答3:

I have been using PostSharp for quite some time and I must say that I am enjoying the ease of use and the simplicity of the implementation.

I must also add that personally, when I use a framework, I always try to stick with a single responsibility framework, unless the framework contains a lot of components that I need or compliments the core.