2014-12-16 11 views
12

Ich habe zwei Schnittstellen:Registrieren ‚halbgeschlossenen‘ generische Komponente

public interface IQuery<TResult> { } 

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

Ein Beispiel für eine geschlossene Durchführung von 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); 
    } 
} 

Ich kann geschlossen generische Implementierungen von IQueryHandler<,> registrieren und löse mit Diese Komponente Registrierung:

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

Allerdings, was ich gerne tun würde ist eine offene generische Implementierung lösen, die „halb geschlossen“ (dh einen generischen TQuery Typen Parameter gibt):

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

Als ich versuchte, IQueryHandler<GetById<Event>, Event> Ich habe diese Ausnahme zu beheben:

eine Ausnahme vom Typ 'Castle.MicroKernel.Handlers.GenericHandlerTypeMismatchException' aufgetreten in Castle.Windsor.dll wurde aber in Benutzercode

Zusätzliche Informationen nicht behandelt: Typen Queries.GetById'1 [[Models.Event, Domain, Version = 1.0.0.0, Kultur = neutral, PublicKeyTok en = null]], Model.Event erfüllt nicht die allgemeinen Einschränkungen des Implementierungstyps Queries.GetByIdHandler'1 der Komponente 'Queries.GetByIdHandler'1'. Dies ist höchstwahrscheinlich ein Fehler in Ihrem Code.

Es sieht aus wie der Typ erfolgreich registriert hat, und die Zwänge erfüllt sind, soweit ich das beurteilen kann (Event eine Klasse und implementiert IIdentity). Was fehlt mir hier? Versuche ich etwas zu tun, mit dem Windsor nicht zurechtkommt?

Antwort

5

(Ich bin dieses Posting nicht als Antwort auf, ebenso wie einige nützliche Informationen, die für einen Kommentar zu viel Informationen ist.)

Während dieser Code in Castle versagt:

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

Die gleiche in Simple Injector Werke:

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

Danke, es sieht aus wie dies ein Problem mit Windsor ist dann – AlexFoxGill

+1

ich weiter untersucht habe und ich denke, du hast Recht, so das die richtige answe ist r: Windsor kann es nicht tun. Simple Injector sieht für mein Projekt immer besser aus – AlexFoxGill