C# AOP 自定义属性 Unity

C# AOP Custom attribute Unity

我正在尝试开发自定义属性以修饰方法,当我这样做时,我希望它们成为属性的 "catched",以便它决定如何处理异常。

我特别知道有两种方法可以做到这一点: - PostSharp - 企业库 Unity

我想避免第一个,我想继续使用 Unity,因为我们已经在使用 Enterprise Library。

所以,为了完成这项工作,我做了以下工作:

我的呼叫处理程序:

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

我的class用属性修饰的方法

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

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

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

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

有可能实现吗?

谢谢大家

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

这种拦截依赖于 Unity 在您通过 Unity DI 容器创建对象时包装您的对象。

即使您不使用 DI 容器,PostSharp 拦截也能正常工作。

如果您不使用 DI 容器,(IMO) 最好保持原样并且不要将 DI 容器引入您的代码库。看我的文章here.

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

我积极致力于 NConcern .NET AOP Framework 一个新的开源项目。你可以试试它来做你需要的。

用于管理异常处理的方面

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.Weave<ExceptionHandlingAspect>(method => method.IsDefined(typeof(LoggingCallHandlerAttribute), true);