【问题标题】:C# AOP Custom attribute UnityC# AOP 自定义属性 Unity
【发布时间】:2015-09-01 09:11:50
【问题描述】:

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

我特别知道有两种技术可以做到这一点: - PostSharp - 企业图书馆统一

我想避免第一个,我想继续使用 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 };
    }
}

我的类带有用属性修饰的方法

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

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

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

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

有可能实现吗?

谢谢你们。

【问题讨论】:

    标签: c# unity-container aop


    【解决方案1】:

    我积极致力于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);
    

    【讨论】:

      【解决方案2】:

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

      当您通过 Unity DI 容器创建对象时,此类拦截依赖于 Unity 来包装您的对象。

      即使您不使用 DI 容器,PostSharp 拦截也将起作用。

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

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

      【讨论】:

        猜你喜欢
        • 2014-09-13
        • 1970-01-01
        • 1970-01-01
        • 2012-02-15
        • 1970-01-01
        • 1970-01-01
        • 2017-05-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多