注册“半闭合”通用组件

本文关键字:组件 半闭合 注册 | 更新日期: 2023-09-27 18:34:20

我有两个接口:

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.Windsor中发生了类型为"Castle.MicroKernel.Handlers.GenericHandlerTypeMismatchException"的异常.dll但未在用户代码中处理

其他信息:类型 Query.GetById'1[[Models.Event,

Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], Models.Event 不满足组件 'Queries.GetByIdHandler'1' 的实现类型 Query.GetByIdHandler'1 的泛型约束。这很可能是代码中的错误。

看起来该类型已成功注册,并且据我所知满足约束(Event是一个类并实现IIdentity(。我在这里错过了什么?我是否想做一些温莎无法应付的事情?

注册“半闭合”通用组件

(

我不是把它作为答案发布,只是一些有用的信息,对于评论来说信息太多了。

虽然 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>>();
}

简单注射器中的相同内容有效:

public void GetInstance_GetByIdHandler_Succeeds()
{
    var container = new SimpleInjector.Container();
    container.RegisterOpenGeneric(
        typeof(IQueryHandler<,>),
        typeof(GetByIdHandler<>));
    var x = container.GetInstance<IQueryHandler<GetById<Event>, Event>>();
}