我正在尝试在我的Xamarin应用程序中创建异常拦截器。现在我正试图拦截服务的方法:从视图模型到商务逻辑的调用(所有在一个项目中,完整的.net标准2)。
我依靠this回答(使用autofac)并发现它简单而聪明。它工作正常,我添加一个try-catch来获取我的异常,到目前为止一切顺利。但后来我尝试在DTO对象类型中返回异常。我们所有的服务都返回一个源自DTOBase
抽象类的DTO类的Task。这些类只包含对值的引用和名为IEnumerable
的异常的Errors
。所以基本上,我尝试捕获异常,将它放在错误列表中并返回我的对象。我完成了这段代码:
public class ExceptionInterceptorBehaviour : IInterceptor
{
public void Intercept(IInvocation invocation)
{
invocation.Proceed();
var method = invocation.MethodInvocationTarget;
var isAsync = method.GetCustomAttribute(typeof(AsyncStateMachineAttribute)) != null;
if (isAsync && typeof(Task).IsAssignableFrom(method.ReturnType))
{
invocation.ReturnValue = InterceptAsync((dynamic)invocation.ReturnValue);
}
}
private static async Task InterceptAsync(Task task)
{
await task.ConfigureAwait(false);
}
private static async Task<T> InterceptAsync<T>(Task<T> task)
{
try
{
T result = await task.ConfigureAwait(false);
return result;
}
catch (Exception e)
{
if (typeof(DTOBase).IsAssignableFrom(typeof(T)))
{
var ret = Activator.CreateInstance(typeof(T));
(ret as DTOBase).Errors.Add(e);
return (T)ret;
}
throw e;
}
}
}
我的问题是应用程序在Task<T> InterceptAsync<T>(Task<T> task)
返回时崩溃。没有异常,调试器中没有暂停模式只是一个简单的崩溃。我怀疑是分段错误,但是我的演员确实有效(我测试了它)并且我确实返回了Task<T>
并将其分配给Task<T>
对象。
我错过了什么吗?我不明白为什么它会像那样崩溃。
这是在iOS上发生的吗? Xamarin有一些由其底层平台定义的limitations。动态代码就是其中之一。避免使用dynamic
。
所以,我考虑了rubo的答案并用dynamic
变量重写我的代码并最终得到:
public class ExceptionInterceptorBehaviour : IInterceptor
{
public void Intercept(IInvocation invocation)
{
invocation.Proceed();
var method = invocation.MethodInvocationTarget;
var isAsync = method.GetCustomAttribute(typeof(AsyncStateMachineAttribute)) != null;
if (isAsync && typeof(Task).IsAssignableFrom(method.ReturnType))
{
if (method.ReturnType.IsGenericType)
{
invocation.ReturnValue = typeof(ExceptionInterceptorBehaviour)
.GetMethod("InterceptGenericAsync", BindingFlags.Instance | BindingFlags.NonPublic)
.MakeGenericMethod(method.ReturnType.GenericTypeArguments[0])
.Invoke(this, new object[] { invocation.ReturnValue });
}
else
{
invocation.ReturnValue = InterceptAsync((Task)invocation.ReturnValue);
}
}
}
private async Task InterceptAsync(Task task)
{
await task.ConfigureAwait(false);
}
private async Task<T> InterceptGenericAsync<T>(Task<T> task)
{
try
{
object result = await task.ConfigureAwait(false);
return (T)result;
}
catch (Exception e)
{
if (typeof(DTOBase).IsAssignableFrom(typeof(T)))
{
var ret = Activator.CreateInstance(typeof(T));
(ret as DTOBase).Errors.Add(e);
return (T)ret;
}
throw e;
}
}
}
有趣的事实是,当我试图在调试中退出InterceptGenericAsync
时,代码仍然崩溃,但是如果我让它运行它可以正常工作,这很奇怪和可怕。我没有在iOS上测试这个解决方案,我不确定它是否正常工作。