我正在尝试开发一个自定义属性来装饰方法,当我这样做时,我希望它们能够被捕获"通过属性,它决定如何处理异常。
我特别注意两种技术: - 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]属性来装饰一个方法。
如果确实需要容器,可以考虑使用容器,但是有一个适合所有目的的容器(至少现在......)会很好。
有可能实现这个目标吗?
谢谢你们。
答案 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进行拦截。但这需要您在创建对象时手动包装它们。