c# AOP自定义属性统一

本文关键字:自定义属性 AOP | 更新日期: 2023-09-27 18:10:43

我试图开发一个自定义属性来装饰方法,当我这样做时,我希望它们被属性"捕获",因此它决定如何处理异常。

我知道有两种方法可以做到这一点:——PostSharp- Enterprise Library Unity

我想避免第一个,我想继续使用Unity,因为我们已经使用了企业库。

因此,为了使它工作,我做了以下操作:

我的调用处理程序:

public class LoggingCallHandler : ICallHandler
{
    public bool Rethrow
    {
        get; set;
    }
    public bool Log
    {
        get; set;
    }
    public int Order
    {
        get; set;
    }
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        var result = getNext().Invoke(input, getNext);
        if (result.Exception != null)
        {
            if (this.Rethrow)
                throw result.Exception;
            if (this.Log)
                this.LogException(result.Exception);
        }
        return result;
    }
    private void LogException(Exception ex)
    {
        //  Do stuff
    }
}

自定义属性

public class LoggingCallHandlerAttribute : HandlerAttribute
{
    private bool rethrow;
    private bool log;
    public LoggingCallHandlerAttribute(bool rethrow, bool log = false)
    {
        this.rethrow = rethrow;
        this.log = log;
    }
    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new LoggingCallHandler() { Rethrow = this.rethrow, Log = this.log };
    }
}

我的类,方法用属性

装饰
 public class TestManager
{
    [LoggingCallHandler(false, false)]
    public void DoStuff()
    {
        throw new Exception("TEST");
    }
}

当我运行这个方法时,没有AOP发生。

我知道Unity可能依赖或完全依赖于容器。但我们目前没有使用任何这些,所以我们只想用[LoggingCallHandler]属性装饰一个功能,仅此而已。

如果容器确实是必要的,可以考虑,但最好有一个适合所有用途的容器(至少现在…)。

这有可能实现吗?

谢谢大家

c# AOP自定义属性统一

我积极致力于NConcern . net AOP框架——一个新的开源项目。你可以试着做你需要做的事。

管理异常处理的方面

public class ExceptionHandlingAspect : IAspect
{
    private void Log(Exception exception)
    {
        //...
    }
    public IEnumerable<IAdvice> Advise(MethodInfo method)
    {
        //advise only if method is tagged.
        if (Attribute.IsDefined(method, typeof(LoggingCallHandlerAttribute))
        {
            //get attribute
            var attribute = method.GetCustomAttributes(typeof(LoggingCallHandlerAttribue))[0] as LoggingCallHandlerAttribute;
            //describe how yo rewrite method.
            yield return Advice.Basic.Arround(invoke =>
            {
                try { invoke(); } //call original code
                catch (Exception e)
                {
                     if (attribute.Rethrow)
                     {
                         throw;
                     }
                     if (attribute.Log)
                     {
                         this.Log(e);
                     }
                }
            });
        }
    }
}

为LoggingCallHandlerAttribute属性的所有方法附加aspect;

Aspect.Weave<ExceptionHandlingAspect>(method => method.IsDefined(typeof(LoggingCallHandlerAttribute), true);

如果你不使用Unity容器来构造你的对象,那么拦截(通过ICallHandler)将不起作用。

当你通过Unity DI容器创建对象时,这种拦截依赖于Unity来包装它们。

即使你不使用DI容器,PostSharp拦截也会起作用。

如果您不使用DI容器,(在我看来)最好还是保持原样,不要在代码库中引入DI容器。请看我的文章。

你可能还想考虑使用DynamicProxy进行拦截。但是这需要您在创建对象时手动包装它们。