2009-06-10 3 views
4

Ich habe zwei Schnittstellen, eine generische und eine nicht-generische, der eine inheritence Hierarchie haben:Wie listet ich alle Elemente auf, die eine generische Schnittstelle implementieren?

public interface IGenericRelation<TParent, TChild> : IRelation 

public interface IRelation 

Der generische eine von mehreren Serversteuer implementiert ist, die dynamisch und ich wünsche aufzuzählen auf die Sammlung von Kontrollen geladen werden, die diese Schnittstelle implementieren. Ich kann wie folgt vorgehen

foreach (IRelation relationControl in this.uiPlhControls.Controls.OfType<IRelation) 
    { ... } 

Aber was ich wirklich in der Lage sein möchte, ist zu tun ...

foreach (IGenericRelation<,> relationControl in this.uiPlhControls.Controls.OfType<IGenericRelation<,>) 
    { ... } 

und dann in der Lage sein, die relationControl mit den Typen zu verwenden, die sie geliefert als dann hätte ich Zugriff auf die stark typisierten Eigenschaften, die in IGenericRelation verfügbar sind. Leider ist das nicht möglich, da ich die Typparameter nicht weglassen kann.

Kennt jemand eine Möglichkeit zum Aufzählen der Steuerelemente, die eine generische Schnittstelle implementieren, damit ich nicht mehrere Schleifen schreiben muss? Vielleicht mit Reflektion?

+0

Ich erinnere mich an eine frühe Linq-Probe, die genau das tat, aber als ich Linq sah, konnte ich es nicht finden. Ich beobachte diesen Raum. . . –

Antwort

3

Dies ist nicht möglich, da IGenericRelation<T,F> eine völlig unterschiedliche Art von IGenericRelation<G,I> ist. Wenn Sie Zugriff auf bestimmte Eigenschaften benötigen, die allen IGenericRelation entsprechen, müssen Sie sie entweder auf der Ebene IRelation implementieren oder eine dritte Schnittstelle zwischen IRelation und IGenericRelation<,> implementieren, die diese implementiert. Der Grund dafür ist, dass der Compiler keine Mittel hat, um abzuleiten, welche Typen er zu implementieren erwartet.

Der einfachste Weg, um dies zu realisieren ist Ihre beiden Eigenschaften als object auf der höheren Ebene (entweder IRelation oder eine Zwischen-Schnittstelle) und stark typisierte am IGenericRelation<,> Ebene umzusetzen.

1

Auf welche stark typisierten Eigenschaften möchten Sie zugreifen? Wenn sie stark typisiert sind, weil sie die Eingabetypen des generischen Typs sind, können Sie nicht auf sie zugreifen, ohne die Typen in Ihrer foreach-Schleife zu liefern. Wenn sie stark typisiert sind, aber nicht bezogen auf die bereitgestellten Typen, können Sie sie in die IRelation-Klasse verschieben?

Dies wird mehr Sinn, mit einem Codebeispiel machen - lassen Sie uns sagen, dass Ihre Klassen sind so etwas wie:

public IRelation 
{ 
    public string RelationshipType { get; set; } 
} 

public IGenericRelation<TParent, TChild> : IRelation 
{ 
    public TParent Parent { get; set; } 
    public TChild Child { get; set; } 
} 

Wenn Ihre Liste enthalten ist ein IGenericRelation<Foo, Bar> und ein IGenericRelation<Fizz, Buzz> Sie nicht aufzählen kann und beide zurück, ohne zu wissen welche konkreten Typ, den Sie suchen: (. Beachten Sie, dass ich musste auch die Art der relationControl in der foreach ändern aus Ihrem Beispiel-Code, so die mögliche Verwendung einen Sinn macht)

//Theoretical, non-compiling example.... 
foreach (IGenericRelation<,> relationControl in this.uiPlhControls.Controls.OfType<IGenericRelation<,>>) 
{ 
    //This wouldn't work for type IGenericRelation<Fizz, Buzz> 
    relationControl.Parent.FooProperty = "Wibble"; 

    //You would be able to access this, but there is no advantage over using IRelation 
    relationControl.RelationshipType = "Wibble"; 
} 


Grundsätzlich kann es hilfreich sein, die gleiche wie C++ Templat Klassen zu denken .NET Generika (ich weiß, dass die Umsetzung unterschiedlich ist, aber die Wirkung ist in dieser Hinsicht das gleiche). Stellen Sie sich vor, dass zur Kompilierungszeit Ihr gesamter Code auf Anwendungen der IGenericRelation-Klasse überprüft wird und konkrete, nicht generische Klassen erstellt werden, indem eine Suche nach den Schlüsselwörtern TParent und TChild durchgeführt und durch den angeforderten Typ ersetzt wird. Da die beiden erstellten Klassen so unabhängig voneinander sind wie zwei andere .NET-Klassen, macht es keinen Sinn, "alle Klassen anzufordern, die als diese Vorlage gestartet wurden". Am besten können Sie nach einer gemeinsamen Basisklasse oder Schnittstelle suchen - in diesem Fall IRelation.

+0

Ja, sie sind die Eingabetypen der generischen Schnittstelle. –

Verwandte Themen