2011-01-06 7 views
1

Ich versuche zu überprüfen, ob eine offene generische Typdefinition eine offene generische Schnittstelle implementiert. Schauen Sie sich die Probe unter:So überprüfen Sie, ob eine generische Typdefinition von einer anderen generischen Typdefinition erbt

public interface IService<T> { } 

public class ServiceImpl<T> : IService<T> { } 

private static bool OpenGenericTypeImplementsOpenGenericInterface(
    Type derivedType, Type interfaceType) 
{ 
    return derivedType.GetInterfaces().Contains(interfaceType); 
} 

[TestMethod] 
public void Verify() 
{ 
    Type openGenericImplementation = typeof(ServiceImpl<>); 

    Type expectedInterfaceType = typeof(IService<>); 

    bool implDoesImplementInterface = OpenGenericTypeImplementsOpenGenericInterface(
     openGenericImplementation, expectedInterfaceType); 

    // This assert fails. Why? 
    Assert.IsTrue(implDoesImplementInterface); 
} 

Ich fand heraus, dass der zurückTyp aus der Type.GetInterfaces() Methode nicht die Art von typeof(IService<>) zurück entspricht. Ich kann nicht herausfinden, warum das so ist und wie man korrekt überprüft, ob eine generische Typdefinition irgendeine andere generische Typdefinition erbt oder implementiert.

Was ist hier los und wie löse ich dieses Problem beheben?

+0

In Zeile: Assert.IsTrue (OpenGenericTypeImplements) ;, was ist OpenGenericTypeImplements? – HABJAN

+1

@HABJAN: Sie haben Recht. Einen Tippfehler gemacht. Behoben. – Anne

Antwort

3

Das Problem ist, dass GetInterfaces kehrt Typen geschlossen, damit Sie sie GetGenericTypeDefinition verwenden müssen öffnen:

public static bool ImplementsOpenInterface(Type type, Type openInterfaceType) { 
    Contract.Requires(type != null); 
    Contract.Requires(openInterfaceType != null); 
    Contract.Requires(openInterfaceType.IsGenericTypeDefinition); 
    Type[] interfaces = type.GetInterfaces(); 
    if (interfaces == null) { 
     return false; 
    } 

    return interfaces 
     .Where(x => x.IsGenericType) 
     .Select(x => x.GetGenericTypeDefinition()) 
     .Any(x => x == openInterfaceType); 
} 
+1

Kühl. Das funktioniert. Vielen Dank. – Anne

+1

Resharper sagt mir, dass GetInterfaces niemals Null zurückgibt – Sam

1

GetInterfaces() wird ein geschlossenes Type-Objekt mit dem generischen Parameter zurückgeben, mit dem es die Schnittstelle implementiert.

Stattdessen verwenden LINQ:

return derivedType.GetInterfaces().Any(i => 
    i == interfaceType 
|| (i.ContainsGenericParameters && i.GetGenericTypeDefinition() == interfaceType)) 

Dieser Code überprüft, ob eine der Schnittstellen, die es eine parametrisierte Version Ihrer Schnittstelle implementiert.

1

mit diesem Ihre Methode ändern und es wird funktionieren:

private static bool OpenGenericTypeImplementsOpenGenericInterface(
    Type derivedType, Type interfaceType) 
{ 
    return derivedType.GetInterface(interfaceType.Name) != null; 
} 
+0

Beachten Sie, dass 'interfaceType.Name'' IService'1' ist. – SLaks

+0

Ok, was versuchst du zu sagen? – HABJAN

+0

Nur, dass der Name nicht das ist, was Sie erwarten könnten. Deine Antwort ist richtig. – SLaks

0

Ich hatte eine Notwendigkeit, Erweitern Sie diese Option, um die Typvererbung zusätzlich zu den Schnittstellen einzuschließen. Hier ist, was ich kam mit:

interface IFace<T> {} 
class Impl<T> : IFace<T> {} 
class Derived<T> : Impl<T> {} 

public static bool InheritsFrom(this Type tDerived, Type tBase) 
{ 
    if (tDerived.IsSubtypeOf(tBase)) return true; 
    var interfaces = tDerived.GetInterfaces() 
          .Select(i => i.IsGenericType ? i.GetGenericTypeDefinition() : i); 
    return interfaces.Contains(tBase); 
} 
public static bool IsSubtypeOf(this Type tDerived, Type tBase) 
{ 
    var currentType = tDerived.BaseType; 
    while (currentType != null) 
    { 
     if (currentType.IsGenericType) 
      currentType = currentType.GetGenericTypeDefinition(); 
     if (currentType == tBase) return true; 
     currentType = currentType.BaseType; 
    } 
    return false; 
} 

Beachten Sie, dass während dieser Methoden auf zwei beliebigen Arten arbeiten, sie gehen davon aus, dass, wenn ein generischer Typ übergeben wird, der Typ geöffnet ist (das heißt, es ist die generische Typdefinition ohne definierte Typparameter).

Verwandte Themen