Регистрация "полузакрытого" общего компонента
У меня есть два интерфейса:
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()
Однако то, что я хотел бы сделать, это разрешить открытую общую реализацию, которая является "наполовину закрытой" (т.е. указывает общий тип типа 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>
, я получил это исключение:
Исключение типа "Castle.MicroKernel.Handlers.GenericHandlerTypeMismatchException" произошло в Castle.Windsor.dll, но не было обработано в коде пользователя
Дополнительная информация: Типы Queries.GetById'1 [[Models.Event, Domain, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null]], Models.Event не удовлетворяют общим ограничениям типа запроса. GetByIdHandler'1 компонента 'Queries.GetByIdHandler'1'. Скорее всего, это ошибка в коде.
Похоже, что тип успешно зарегистрирован, и ограничения выполняются, насколько я могу судить (Event
является классом и реализует IIdentity
). Что мне здесь не хватает? Я пытаюсь сделать то, с чем не справляется Виндзор?
Ответы
Ответ 1
(Я не размещаю это как ответ, так же как некоторая полезная информация, которая слишком много информации для комментария.)
Пока этот код в 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>>();
}