2014-02-22 9 views
6

Ich bin ein generischer Abfrage Dispatcher bauen. Die Idee ist, wie folgt:Typ Rückschluss mit Schnittstellen und generischen Einschränkungen

  • Eine generische Schnittstelle IQuery<T> die
  • Eine konkrete Abfrageklasse hat einige Getter und Setter (implementierende IQuery<T>)
  • Eine generische Schnittstelle IQueryHandler<TReturnType, TQuery> mit einer einzigen Methode ein Abfrageobjekt darstellt, erhält ein TQuery (mit einer Einschränkung auf TQuery: IQuery<TReturnType>) und gibt einen TReturnType
  • Lader Beton IQueryHandler Implementierung, die ein konkretes ConcreteQuery und gibt eine TQuery
  • erhalten
  • Eine QueryDispatcher, die eine einzige Methode hat, die eine Abfrage empfängt und ein Ergebnis zurückgibt. Die konkrete Klasse sucht den richtigen Handler aus einem DI-Container.

Das Problem ist, dass ich nicht Typinferenz, wenn ich die Fetch Methode auf den QueryDispatcher nennen. Gibt es etwas, was ich tun kann, um Typinferenz zu bekommen, oder ist das nur eine Einschränkung von C#?

In der Theorie sollte es wissen, was die Typargumente sind, da es einen Parameter TQuery empfängt, der eine Beschränkung auf eine IQuery<TReturnType hat.

Dies ist der Code:

class ConcreteClass // This is the class of which I want to query objects 
{ 
} 

Abfrage-Schnittstelle + Beton Abfrageklasse

interface IQuery<T> 
{ 
} 

public class ConcreteQuery : IQuery<ConcreteClass> 
{ 
} 

QueryHandler Schnittstelle + Beton Abfrage-Handler

interface IQueryHandler<TReturnType, TQuery> where TQuery : IQuery<TReturnType> 
{ 
    TReturnType Fetch(TQuery query); 
} 

class ConcreteQueryHandler : IQueryHandler<ConcreteClass, ConcreteQuery> 
{ 
    ConcreteClass Fetch(ConcreteQuery query) 
    { 
    } 
} 

QueryDispatcher (ein DI-Container verwendet zu lösen der richtige Handler)

class QueryDispatcher 
{ 
    TReturnType Fetch<TReturnType, TQuery>(TQuery query) 
     where TQuery : IQuery<TReturnType> 
    { 
     return myDIcontainer.Get<IQueryHandler<T, TQuery>>().Fetch(query); 
    } 
} 

Nun, wenn ich die QueryDispatcher wie diesen bekomme ich einen Fehler:

var queryDispatcher = new QueryDispatcher(); 
var c = queryDispatcher.Fetch(new ConcreteQuery()); 

Wenn ich die alles Typargumente liefern korrekt funktioniert:

var c = queryDispatcher.Fetch<ConcreteClass, ConcreteQuery>(new ConcreteQuery()); 
+0

denke nicht, dass Sie andere Wahl haben, wie es jetzt nicht mehr kann, wie TReturnType zu lösen –

+0

Die Frage ist, Ist das eine Einschränkung von C#? – Kenneth

+0

@Kenneth Wenn Sie die 'var' in den echten Typ ändern, hilft es? –

Antwort

0

Was Sie wollen, ist ein zweistufiges Typ Inferenz und der Compiler wird es nicht tun.

Sie könnten Ihren Abfragedispatcher überdenken. Betrachten Sie es als etwas, das eine IQuery<TReturnType> nimmt und eine TReturnType zurückgibt.

Versuchen Sie Ihre Anfrage Dispatcher Wechsel zu: „Warum nicht?“

class QueryDispatcher 
{ 
    public TReturnType Fetch<TReturnType>(IQuery<TReturnType> query) 
    { 
     return myDIcontainer 
      .Get<IQueryHandler<TReturnType, IQuery<TReturnType>>>() 
      .Fetch(query); 
    } 
} 
+0

Aber ich bin richtig, dass in der Theorie sollte der Compiler in der Lage sein, es zu tun, aber dass der C# -Compiler ist einfach nicht schlau genug, oder? Das Problem beim Ändern des Abfrage-Dispatchers ist, dass ich dann verschiedene Abfrage-Handler für verschiedene IQuerys nicht auflösen kann – Kenneth

Verwandte Themen