Подтвердить что ты не робот

Регистрация "полузакрытого" общего компонента

У меня есть два интерфейса:

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). Что мне здесь не хватает? Я пытаюсь сделать то, с чем не справляется Виндзор?

4b9b3361

Ответ 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>>();
}