我写了2个拦截,1个是关于验证传递的争论,另一个是错误处理。
拦截#1抛出错误(按预期),自定义对象附加到MethodExecutionArgs.MethodExecutionTag
public class ValidateArguementAttribute : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
...
var state = new ExecutionState
{
ReturnExactErrorMessage = true,
};
args.MethodExecutionTag = state;
throw new ArgumentException(errMsgs.ToString());
但是,此错误处理中会丢失此MethodExecutionTag。
public class ExceptionHandlingWithResponseAttribute : ExceptionHandlingAttribute
{
public override void OnException(MethodExecutionArgs args)
{
base.OnException(args);
ExecutionState state = args.MethodExecutionTag as ExecutionState;
if (state != null)
{
// as debugging, expected to be here, but it's not
}
我通过MethodExecutionArgs.GetHashCode()进行简单的检查,得到不同的值。
我有类似的设计用于网络Api应用程序,它按预期工作,但我无法调试它,因为我正在测试单元测试。
这是一些bug,或者我该如何解决?
答案 0 :(得分:0)
这是设计的。执行标签在各个方面之间是隔离的。
想象一下,您有一个事务和一个缓存方面。两者都在OnEntry中设置执行标记并尝试在OnExit中检索它。来自事务方面的标记被缓存方面覆盖,这会产生可怕的混乱。
需要隔离以避免像这样的令人讨厌的事情。
解决方案可能是将两个方面合并为一个:
public class ValidateArguementAttribute : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
...
var state = new ExecutionState
{
ReturnExactErrorMessage = true,
};
args.MethodExecutionTag = state;
throw new ArgumentException(errMsgs.ToString());
}
public override void OnException(MethodExecutionArgs args)
{
base.OnException(args);
ExecutionState state = args.MethodExecutionTag as ExecutionState;
if (state != null)
{
// as debugging, expected to be here, but it's not
}
}
}
替代地,可以直接处理验证结果,而不是抛出异常。
更新(基于Kelmen的自定义异常的想法):
public class ValidationException : Exception
{
public ExecutionState State { get; private set; }
public ValidationException(ExecutionState state)
{
State = state;
}
}
[Serializable]
public class ValidateArguementAttribute : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
var state = new ExecutionState
{
ReturnExactErrorMessage = true,
};
throw new ValidationException(state);
}
}
[Serializable]
public class ExceptionHandlingWithResponseAttribute : OnExceptionAspect
{
public override void OnException(MethodExecutionArgs args)
{
base.OnException(args);
ValidationException validationException = args.Exception as ValidationException;
if (validationException != null)
{
// handle the exception
}
else
{
// just rethrow
args.FlowBehavior = FlowBehavior.RethrowException;
}
}
}