C# Code Snippet: Testen, ob ein Typ ein bestimmtes Interface implementiert
Manchmal möchte man testen, ob ein (erst) zur Laufzeit bekanntes Objekt ein bestimmtes Interface implementiert. Die Type-Klasse bietet hierfür die Funktion FindInterfaces(), die allerdings unter Umständen etwas mehr Overhead darstellt, als eigentlich nötig ist. Wenn man das Problem häufiger hat, ist hier ein Ansatz, um den Aufwand zu verringern. Es ist eine Implementierung als Extension Method und setzt daher Framework 3.5 oder einen kleinen Kniff voraus; Es ist allerdings auch nicht weiter schwierig, es als normale, statische Funktion zu implementieren – einfach das this in der Parameterliste entfernen.
-
[DebuggerStepThrough]
-
public static bool HasInterface(this Type type, Type interfaceType)
-
{
-
Type[] array = type.FindInterfaces(
-
delegate(Type typeObj, Object criteriaObj)
-
{
-
return typeObj.Equals((Type)criteriaObj);
-
},
-
interfaceType
-
);
-
return array.Length > 0;
-
}
Beispiel zur Anwendung:
Der Vergleich wird platzsparend in Form einer anonymen Funktion (die delegate) durchgeführt, das [DebuggerStepThrough]-Attribut sorgt dafür, dass der Debugger die Funktion nicht besucht, wenn man Step Into benutzt – spart Zeit und Nerven.
Nachtrag: Will man testen, ob eine Klasse ein bestimmtes, generisches Interface implementiert, ohne dass man den genauen Typparameter kennt oder benennen will, ist die Funktion in ihrer derzeitigen Form ungeeignet. Der Grund: typeof(IList<>) liefert eine Typdefinition, während typeof(IList<int>) einen Typ liefert – Equals schlägt fehl.
Folgende Beobachtung schafft Abhilfe:
Mit einer kleinen Änderung klappt dann alles:
-
[DebuggerStepThrough]
-
public static bool HasInterface(this Type type, Type interfaceType)
-
{
-
Type[] array = type.FindInterfaces(
-
delegate(Type typeObj, Object criteriaObj)
-
{
-
// wenn das Typobjekt generisch ist, aber keine Definition (denn ansonsten greift Equals bereits zu)
-
// und wenn das Vergleichsobjekt eine Typdefinition ist …
-
if (typeObj.IsGenericType && !typeObj.IsGenericTypeDefinition && ((Type)criteriaObj).IsGenericTypeDefinition)
-
// … dann holen wir uns die Typdefinition des Objektes und vergleichen damit
-
return (typeObj.GetGenericTypeDefinition().Equals(criteriaObj));
-
return typeObj.Equals((Type)criteriaObj);
-
},
-
interfaceType
-
);
-
return array.Length > 0;
-
}
Voilá.




Reicht dir der “is”-Operator nicht aus?
Object bb = new Bullet(new Vector2(), 500, 0);
if(bb is IParticle)
{
//bb implementiert IParticle
}
in meinem Fall implementiert Bullet IParticle. Wenn ich als Datentyp Bullet statt Object nehme, meint Resharper sogar, dass das IF immer true wird!
Jap, vollkommen richtig! Ich mach’s auch genau so.
Das Problem mit den generischen Interfaces bleibt allerdings; Ich brauchte das für eine Serialisierungsfunktion, die Listen oder Dictionaries (IDictionary< ,>) gesondert behandelt; Leider kann man diese Typdefinitionen nicht per “is” abgreifen.