2014-12-16 17 views
12

Ho due interfacce:Registrazione

public interface IQuery<TResult> { } 

public interface IQueryHandler<in TQuery, out TResult> 
    where TQuery : IQuery<TResult> 
{ 
    TResult Handle(TQuery q); 
} 

Un esempio di attuazione chiuso di 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); 
    } 
} 

posso registrare e risolvere implementazioni generiche chiusi di IQueryHandler<,> con registrazione di questo componente:

Classes.FromAssemblyContaining(typeof(IQueryHandler<,>)) 
    .BasedOn(typeof(IQueryHandler<,>)) 
    .WithServiceAllInterfaces() 

Tuttavia, ciò che vorrei fare è risolvere un'implementazione generica aperta che è "mezzo chiuso" (cioè specifica un parametro TQuery tipo generico):

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); 
    } 
} 

Quando ho cercato di risolvere IQueryHandler<GetById<Event>, Event> ho questa eccezione:

Un'eccezione di tipo 'Castle.MicroKernel.Handlers.GenericHandlerTypeMismatchException' si è verificato in Castle.Windsor.dll ma non è stata gestita nel codice utente

Ulteriori informazioni: Tipi Queries.GetById'1 [[Models.Event, Domain, Version = 1.0.0.0, Cultura = neutrale, PublicKeyTok en = null]], Models.Event non soddisfa i vincoli generici del tipo di implementazione Queries.GetByIdHandler'1 del componente 'Queries.GetByIdHandler'1'. Questo è molto probabilmente un bug nel tuo codice.

Sembra che il tipo ha registrato con successo, ei vincoli sono soddisfatti per quanto posso dire (Event è una classe e implementa IIdentity). Cosa mi manca qui? Sto cercando di fare qualcosa con cui Windsor non può farcela?

risposta

5

(io non sto postando questo come una risposta, proprio come alcune informazioni utili che sono troppe informazioni per un commento.)

Mentre questo codice in Castello non riesce:

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

Il stessa cosa in Simple Injector opere:

public void GetInstance_GetByIdHandler_Succeeds() 
{ 
    var container = new SimpleInjector.Container(); 

    container.RegisterOpenGeneric(
     typeof(IQueryHandler<,>), 
     typeof(GetByIdHandler<>)); 

    var x = container.GetInstance<IQueryHandler<GetById<Event>, Event>>(); 
} 
+0

Grazie, sembra che questo è un problema con il Windsor allora – AlexFoxGill

+1

ho indagato ulteriormente e penso che tu abbia ragione quindi questo è il corretto answe r: Windsor non può farlo. Simple Injector è sempre più bello per il mio progetto – AlexFoxGill