无法将解析的对象强制转换为通用抽象autofac C#
嘿,我尝试将我的对象转换为这个对象应该实现的接口。但在执行代码期间,我有以下错误: 无法将GetTreeHandler类型的对象强制转换为IQueryHandler,IQuery 为什么??一切似乎都很好 有没有不使用动态的想法 QueryDispatcher无法将解析的对象强制转换为通用抽象autofac C#,c#,asp.net,asp.net-core,autofac,C#,Asp.net,Asp.net Core,Autofac,嘿,我尝试将我的对象转换为这个对象应该实现的接口。但在执行代码期间,我有以下错误: 无法将GetTreeHandler类型的对象强制转换为IQueryHandler,IQuery 为什么??一切似乎都很好 有没有不使用动态的想法 QueryDispatcher public async Task<TResult> ExecuteAsync<TResult>(IQuery<TResult> query) { if (query =
public async Task<TResult> ExecuteAsync<TResult>(IQuery<TResult> query)
{
if (query == null)
{
throw new ArgumentNullException("Query can not be null.");
}
var handlerType = typeof (IQueryHandler<,>).MakeGenericType(query.GetType(), typeof (TResult));
var handler = _context.Resolve(handlerType);
IQueryHandler<IQuery<TResult>, TResult> castedHandler = (IQueryHandler<IQuery<TResult>, TResult>) handler;
return (TResult) await castedHandler.ExecuteAsync(query);
}
公共异步任务ExecuteAsync(IQuery查询)
{
if(查询==null)
{
抛出新ArgumentNullException(“查询不能为null”);
}
var handlerType=typeof(IQueryHandler).MakeGenericType(query.GetType(),typeof(TResult));
var handler=_context.Resolve(handlerType);
IQueryHandler castedHandler=(IQueryHandler)处理程序;
return(TResult)wait castedHandler.ExecuteAsync(query);
}
GetTreeHandler
public class GetTreeHandler : IQueryHandler<GetTree, Tree>
{
private readonly ProductContext _context;
public string Name { get; set; }
public GetTreeHandler(ProductContext context)
{
_context = context;
}
public async Task<Tree> ExecuteAsync(GetTree query)
=> await Task.FromResult(
_context.Trees.FirstOrDefault(x => x.Id == query.Id)
);
}
公共类GetTreeHandler:IQueryHandler
{
私有只读ProductContext\u上下文;
公共字符串名称{get;set;}
公共GetTreeHandler(ProductContext上下文)
{
_上下文=上下文;
}
公共异步任务ExecuteAsync(GetTree查询)
=>等待任务.FromResult(
_context.Trees.FirstOrDefault(x=>x.Id==query.Id)
);
}
编辑
我当前的解决方案(部分有效):
公共异步任务ExecuteAsync(IQuery查询),其中TResult:class
{
if(查询==null)
{
抛出新ArgumentNullException(“查询不能为null”);
}
var handlerType=typeof(IQueryHandler).MakeGenericType(query.GetType(),typeof(TResult));
var handler=_context.Resolve(handlerType);
返回等待(任务)
handler.GetType()
.GetMethod(“ExecuteAsync”)
.Invoke(处理程序,新对象[]{query});
}
为什么部分?
例如:处理人员:
不起作用:
public class GetIndexesHandler : IQueryHandler<GetIndexes, IEnumerable<AssocIndexDto>>
公共类GetIndexesHandler:IQueryHandler
作品:
public class GetIndexesHandler : IQueryHandler<GetIndexes,AssocIndexDto>
公共类GetIndexesHandler:IQueryHandler
正如您所看到的,这两个类实现了相同的接口,但第二个参数类型不同
问题是Resolve方法找不到已注册的服务,但如果我尝试调试此代码,我可以看到所需的服务已正确注册,但找不到
您知道如何解决它吗?您正在尝试将
IQueryHandler
强制转换为IQueryHandler
,但只有当IQueryHandler
被指定为:
interface IQueryHandler<out TQuery, TResult>
另一个选项是指定并注册一个泛型包装器类型,该类型实现了一个缺少TQuery
泛型类型的接口。这样,您可以防止同时使用动态:
public interface IWrapper<TResult>
{
Task<TResult> ExecuteAsync(IQuery<TResult> query);
}
public async Task<TResult> ExecuteAsync<TResult>(IQuery<TResult> query)
{
var wrapperType =
typeof(Wrapper<,>).MakeGenericType(query.GetType(), typeof(TResult));
var wrapper = (IWrapper<TResult>)_context.Resolve(wrapperType);
return wrapper.ExecuteAsync(query);
}
// Don't forget to register this type by itself in Autofac.
public class Wrapper<TQuery, TResult> : IWrapper<TResult>
{
private readonly IQueryHandler<TQuery, TResult> handler;
public Wrapper(IQueryHandler<TQuery, TResult> handler) { this.handler = handler; }
Task<TResult> IWrapper<TResult>.ExecuteAsync(IQuery<TResult> query) =>
this.handler.ExecuteAsync((TQuery)query);
}
公共接口IWrapper
{
任务执行同步(IQuery查询);
}
公共异步任务ExecuteAsync(IQuery查询)
{
变量包装器类型=
typeof(Wrapper).MakeGenericType(query.GetType(),typeof(TResult));
var wrapper=(IWrapper)\ u context.Resolve(wrapperType);
返回wrapper.ExecuteAsync(查询);
}
//不要忘记在Autofac中自行注册此类型。
公共类包装器:IWrapper
{
私有只读IQueryHandler处理程序;
公共包装器(IQueryHandler){this.handler=handler;}
任务IWrapper.ExecuteAsync(IQuery)=>
this.handler.ExecuteAsync((TQuery)查询);
}
不,它没有_context.Resolve返回我“object”类型,我无法对“object”类型执行“ExecuteAsync”方法,所以我决定将其强制转换到适当的接口。GetTreeHandler
implementIQueryHandler
,但不是IQueryHandler
。但是GetTree实现IQuery,所以它应该是正确的,不是吗?有没有机会不用dynamic来做这件事?假设我找到了解决方案,但我不知道这是否是一个好方法。特别是我指的是性能。反射机制是否使用任何动态类型的底层?嗯,我将尝试您的解决方案,因为它看起来很有意义,但我可能找到了解决方案,但它无法正常工作。你想看看我的溶液吗?(编辑部分有问题)@bielu000:你有两个选择,这两个都在我的答案中给出。您使用反射和调用的选项将无法正常工作,因为调用将使用调用异常包装任何抛出的异常,这将混淆日志文件并使处理特定异常(例如验证异常)变得复杂从业务层。编辑:我的错误是找不到处理程序;)请不要为此烦恼;)感谢您的帮助,我将尝试使用您的解决方案改进我的解决方案。wprapper在我的容器中的注册有问题。它抛出包装器尚未注册的异常。但在我看来,我做得对:builder.RegisterGeneric(typeof(querybushwrapper)).As(typeof(iquerybushwrapper)).InstancePerDependency();
public async Task<TResult> ExecuteAsync<TResult>(IQuery<TResult> query)
{
var handlerType =
typeof(IQueryHandler<,>).MakeGenericType(query.GetType(), typeof(TResult));
dynamic handler = _context.Resolve(handlerType);
return (TResult)await castedHandler.ExecuteAsync((dynamic)query);
}
public interface IWrapper<TResult>
{
Task<TResult> ExecuteAsync(IQuery<TResult> query);
}
public async Task<TResult> ExecuteAsync<TResult>(IQuery<TResult> query)
{
var wrapperType =
typeof(Wrapper<,>).MakeGenericType(query.GetType(), typeof(TResult));
var wrapper = (IWrapper<TResult>)_context.Resolve(wrapperType);
return wrapper.ExecuteAsync(query);
}
// Don't forget to register this type by itself in Autofac.
public class Wrapper<TQuery, TResult> : IWrapper<TResult>
{
private readonly IQueryHandler<TQuery, TResult> handler;
public Wrapper(IQueryHandler<TQuery, TResult> handler) { this.handler = handler; }
Task<TResult> IWrapper<TResult>.ExecuteAsync(IQuery<TResult> query) =>
this.handler.ExecuteAsync((TQuery)query);
}