C#如何将AOP用于静态方法?

时间:2013-01-04 20:53:38

标签: c# .net aop

我已经构建了一个c#.net 4.0库。

所有方法都是公开的和静态的。

我想使用方面编程库添加一个方面,它可以执行以下操作:

try block
1. call method (if method throws exception)

catch block
2. log the exception and massage the exception

it is a dll (class library project)

如果有办法在一个类中添加try / catch例程而不是逐个包装所有方法,请指教吗?

2 个答案:

答案 0 :(得分:5)

因为您之前提到过单词static以及基于的其他内容都无法帮助您,因为他们可以在常规方法中添加方面。所以你有两个选择:

手写跟踪装饰器

添加单独的手写跟踪装饰器,它将添加所需的功能而不改变现有代码

  • 优势
    • 简单易懂自己
  • 缺点
    • 几乎没有呼叫上下文。这对于跟踪很重要,如果你想知道实际调用了什么方法以及传递了什么参数等等。
    • 围绕现有代码的新抽象层。您不必调用静态方法,而是必须调用将调用静态方法的Decorator

实施例

// Decorated calls
TraceDecorator.Aspect(() => StaticLogic.SuccessfulCall());
TraceDecorator.Aspect(() => StaticLogic.ExceptionCall());
TraceDecorator.Aspect(() => StaticLogic.SuccessfulCallWithReturn(42));
TraceDecorator.Aspect(() => StaticLogic.ExceptionCallWithReturn(42));

// Decorator itself
public static class TraceDecorator
{
    public static T Aspect<T>(Func<T> func)
    {
        try
        {
            return func();
        }
        catch(Exception ex)
        {
            LogException(ex);

            return default(T);
        }    
    }

    public static void Aspect(Action func)
    {
        try
        {
            func();
        }
        catch(Exception ex)
        {
            LogException(ex);
        }    
    }

    private static void LogException(Exception ex)
    {
        Console.WriteLine("Traced by TraceDecorator: {0}", ex);
    }
}

完整样本here

PostSharp

使用Non-Invasive Tracing & Logging

查看
  • 优势
    • 在不改变现有代码或自行添加属性的情况下广播您的方面,无论您认为合适,
    • 关注点分离:跟踪/日志记录与逻辑分开
    • 还有更多......
  • 缺点
    • 没有什么是免费的。但是有一个功能有限的免费PostSharp版本
    • 有时因为后期编译而与其他工具集成

答案 1 :(得分:0)

参见NConcern .NET AOP Framework,一个开源项目。

示例

你的静态课程

static public class Calculator
{
    static public int Add(int a, int b)
    {
        return a + b;
    }
}

记录器

static public class Logger
{
    static public void Log(MethodInfo method, object[] arguments, Exception exception)
    {
        Console.WriteLine("{0}({1}) exception = {2}", method.Name, string.Join(", ", arguments), exception.Message);
    }
}

方面:登录异常

public class Logging : IAspect
{
    public IEnumerable<IAdvice> Advise(MethodInfo method)
    {
        yield return Advice.Basic.After.Throwing((instance, arguments, exception) => 
        {
            Logger.Log(method, arguments, exception);
        });
    }
}

Joinpoint:计算器方法

var calculatorMethods = new Func<MethodInfo, bool>(method => method.ReflectedType == typeof(Calculator));

激活连接点的日志记录方面

Aspect.Weave<Logging>(calculatorMethods);