C#AOP自定义属性Unity

时间:2015-09-01 09:11:51

标签: c# unity-container aop

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

我特别注意两种技术: - PostSharp - 企业图书馆团结

我想避开第一个,因为我们已经使用了Enterprise Library,所以我想继续使用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]属性来装饰一个方法。

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

有可能实现这个目标吗?

谢谢你们。

2 个答案:

答案 0 :(得分: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);

答案 1 :(得分:0)

如果您不使用Unity容器来构建对象,则拦截(通过ICallHandler)将无效。

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

即使您没有使用DI容器,PostSharp拦截仍然有效。

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

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