我正在尝试在Xamarin应用程序中创建异常拦截器。现在,我正试图拦截服务的方法:从视图模型到业务逻辑的调用(全部在一个项目中,完整的.net标准2)。
我偶然发现了ExcelJet答案(使用autofac),并发现它简单而聪明。一切正常,到目前为止,我添加了一个try-catch来获取异常。
但是后来我尝试以DTO对象类型返回异常。我们所有的服务都返回从value
抽象类派生的DTO类的Task。这些类仅包含对值的引用和名为DTOBase
的异常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>
对象。
我想念什么吗?我不明白为什么它会崩溃。
答案 0 :(得分:0)
这是在iOS上发生的吗? Xamarin由其基础平台定义了一些limitations。动态代码就是其中之一。避免使用dynamic
。
答案 1 :(得分:0)
因此,我考虑了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上测试此解决方案,但不确定它是否有效。