我有两个界面:
public interface IQuery<TResult> { }
public interface IQueryHandler<in TQuery, out TResult>
where TQuery : IQuery<TResult>
{
TResult Handle(TQuery q);
}
IQueryHandler的已关闭实现的示例:
public class EventBookingsHandler : IQueryHandler<EventBookings, IEnumerable<EventBooking>>
{
private readonly DbContext _context;
public EventBookingsHandler(DbContext context)
{
_context = context;
}
public IEnumerable<EventBooking> Handle(EventBookings q)
{
return _context.Set<MemberEvent>()
.OfEvent(q.EventId)
.AsEnumerable()
.Select(EventBooking.FromMemberEvent);
}
}
我可以使用此组件注册注册并解决IQueryHandler<,>
的封闭通用实现:
Classes.FromAssemblyContaining(typeof(IQueryHandler<,>))
.BasedOn(typeof(IQueryHandler<,>))
.WithServiceAllInterfaces()
但是,我想要做的是解决一个开放的通用实现,即半封闭&#34; (即指定通用的TQuery
类型参数):
public class GetById<TEntity> : IQuery<TEntity> where TEntity : class, IIdentity
{
public int Id { get; private set; }
public GetById(int id)
{
Id = id;
}
}
public class GetByIdHandler<TEntity> : IQueryHandler<GetById<TEntity>, TEntity> where TEntity : class, IIdentity
{
private readonly DbContext _context;
public GetByIdHandler(DbContext context)
{
_context = context;
}
public TEntity Handle(GetById<TEntity> q)
{
return _context.Set<TEntity>().Find(q.Id);
}
}
当我尝试解决IQueryHandler<GetById<Event>, Event>
时,我遇到了这个例外:
类型&#39; Castle.MicroKernel.Handlers.GenericHandlerTypeMismatchException&#39;的例外情况发生在Castle.Windsor.dll但未在用户代码中处理
其他信息:类型Queries.GetById&#39; 1 [[Models.Event,Domain,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]],Models.Event不满足通用约束条件实现类型Queries.GetByIdHandler&#39; 1 of component&#39; Queries.GetByIdHandler&#39; 1&#39;。这很可能是您代码中的错误。
看起来类型已成功注册,并且我可以告诉约束满足(Event
是一个类并实现IIdentity
)。我在这里错过了什么?我想做一些温莎无法应对的事情吗?
答案 0 :(得分:5)
(我不会将此作为答案发布,就像一些有用的信息一样,评论的信息太多了。)
虽然Castle中的代码失败了:
public void Resolve_GetByIdHandler_Succeeds()
{
var container = new Castle.Windsor.WindsorContainer();
container.Register(Component
.For(typeof(IQueryHandler<,>))
.ImplementedBy(typeof(GetByIdHandler<>)));
var x = container.Resolve<IQueryHandler<GetById<Event>, Event>>();
}
Simple Injector中同样的事情:
public void GetInstance_GetByIdHandler_Succeeds()
{
var container = new SimpleInjector.Container();
container.RegisterOpenGeneric(
typeof(IQueryHandler<,>),
typeof(GetByIdHandler<>));
var x = container.GetInstance<IQueryHandler<GetById<Event>, Event>>();
}