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

问题描述 投票:0回答:2

我构建了一个 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 例程,而不是一个一个地包装所有方法?

c# .net aop
2个回答
5
投票

因为您提到了单词

static
或其他任何基于的内容都不会帮助您,因为它们能够围绕常规方法添加方面。所以你有两个选择:

手写追踪装饰器

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

  • 好处
    • 简单易学自己写
  • 缺点
    • 几乎没有通话上下文。如果您想知道实际调用了哪些方法以及传递了哪些参数等,这对于跟踪非常重要。
    • 围绕现有代码的新抽象层。您无需调用静态方法,而是必须调用将在内部调用静态方法的装饰器

示例

// 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);
    }
}

完整样本可在此处

PostSharp

使用 postsharp非侵入式跟踪和日志记录

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

0
投票

请参阅 NConsern .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);
© www.soinside.com 2019 - 2024. All rights reserved.