Réponses:
En utilisant la réponse de TcKs, cela peut également être fait avec la requête LINQ suivante:
bool isBar = foo.GetType().GetInterfaces().Any(x =>
x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(IBar<>));
typeof(IBar<,,,>)avec des virgules agissant comme des espaces réservés
Vous devez remonter dans l'arbre d'héritage et trouver toutes les interfaces pour chaque classe dans l'arbre, et comparer typeof(IBar<>) avec le résultat de l'appel Type.GetGenericTypeDefinition si l'interface est générique. C'est un peu douloureux, certainement.
Voir cette réponse et celles-ci pour plus d'informations et de code.
public interface IFoo<T> : IBar<T> {}
public class Foo : IFoo<Foo> {}
var implementedInterfaces = typeof( Foo ).GetInterfaces();
foreach( var interfaceType in implementedInterfaces ) {
if ( false == interfaceType.IsGeneric ) { continue; }
var genericType = interfaceType.GetGenericTypeDefinition();
if ( genericType == typeof( IFoo<> ) ) {
// do something !
break;
}
}
En tant qu'extension de méthode d'assistance
public static bool Implements<I>(this Type type, I @interface) where I : class
{
if(((@interface as Type)==null) || !(@interface as Type).IsInterface)
throw new ArgumentException("Only interfaces can be 'implemented'.");
return (@interface as Type).IsAssignableFrom(type);
}
Exemple d'utilisation:
var testObject = new Dictionary<int, object>();
result = testObject.GetType().Implements(typeof(IDictionary<int, object>)); // true!
J'utilise une version légèrement plus simple de la méthode d'extension @GenericProgrammers:
public static bool Implements<TInterface>(this Type type) where TInterface : class {
var interfaceType = typeof(TInterface);
if (!interfaceType.IsInterface)
throw new InvalidOperationException("Only interfaces can be implemented.");
return (interfaceType.IsAssignableFrom(type));
}
Usage:
if (!featureType.Implements<IFeature>())
throw new InvalidCastException();
Vous devez vérifier par rapport à un type construit de l'interface générique.
Vous devrez faire quelque chose comme ceci:
foo is IBar<String>
car IBar<String>représente ce type construit. La raison pour laquelle vous devez le faire est que si Tn'est pas défini dans votre vérification, le compilateur ne sait pas si vous voulez dire IBar<Int32>ou IBar<SomethingElse>.
Pour faire face au système de type complètement, je pense que vous devez gérer récursion, par exemple IList<T>: ICollection<T>: IEnumerable<T>, sans que vous ne savez pas que , IList<int>finalement , met en œuvre IEnumerable<>.
/// <summary>Determines whether a type, like IList<int>, implements an open generic interface, like
/// IEnumerable<>. Note that this only checks against *interfaces*.</summary>
/// <param name="candidateType">The type to check.</param>
/// <param name="openGenericInterfaceType">The open generic type which it may impelement</param>
/// <returns>Whether the candidate type implements the open interface.</returns>
public static bool ImplementsOpenGenericInterface(this Type candidateType, Type openGenericInterfaceType)
{
Contract.Requires(candidateType != null);
Contract.Requires(openGenericInterfaceType != null);
return
candidateType.Equals(openGenericInterfaceType) ||
(candidateType.IsGenericType && candidateType.GetGenericTypeDefinition().Equals(openGenericInterfaceType)) ||
candidateType.GetInterfaces().Any(i => i.IsGenericType && i.ImplementsOpenGenericInterface(openGenericInterfaceType));
}
Tout d'abord public class Foo : IFoo<T> {}ne compile pas car vous devez spécifier une classe au lieu de T, mais en supposant que vous faites quelque chose commepublic class Foo : IFoo<SomeClass> {}
alors si tu le fais
Foo f = new Foo();
IBar<SomeClass> b = f as IBar<SomeClass>;
if(b != null) //derives from IBar<>
Blabla();
Dans le cas où vous vouliez une méthode d'extension qui prendrait en charge les types de base génériques ainsi que les interfaces, j'ai développé la réponse de sduplooy:
public static bool InheritsFrom(this Type t1, Type t2)
{
if (null == t1 || null == t2)
return false;
if (null != t1.BaseType &&
t1.BaseType.IsGenericType &&
t1.BaseType.GetGenericTypeDefinition() == t2)
{
return true;
}
if (InheritsFrom(t1.BaseType, t2))
return true;
return
(t2.IsAssignableFrom(t1) && t1 != t2)
||
t1.GetInterfaces().Any(x =>
x.IsGenericType &&
x.GetGenericTypeDefinition() == t2);
}
Méthode pour vérifier si le type hérite ou implémente un type générique:
public static bool IsTheGenericType(this Type candidateType, Type genericType)
{
return
candidateType != null && genericType != null &&
(candidateType.IsGenericType && candidateType.GetGenericTypeDefinition() == genericType ||
candidateType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == genericType) ||
candidateType.BaseType != null && candidateType.BaseType.IsTheGenericType(genericType));
}
Essayez l'extension suivante.
public static bool Implements(this Type @this, Type @interface)
{
if (@this == null || @interface == null) return false;
return @interface.GenericTypeArguments.Length>0
? @interface.IsAssignableFrom(@this)
: @this.GetInterfaces().Any(c => c.Name == @interface.Name);
}
Pour le tester. créer
public interface IFoo { }
public interface IFoo<T> : IFoo { }
public interface IFoo<T, M> : IFoo<T> { }
public class Foo : IFoo { }
public class Foo<T> : IFoo { }
public class Foo<T, M> : IFoo<T> { }
public class FooInt : IFoo<int> { }
public class FooStringInt : IFoo<string, int> { }
public class Foo2 : Foo { }
et la méthode d'essai
public void Test()
{
Console.WriteLine(typeof(Foo).Implements(typeof(IFoo)));
Console.WriteLine(typeof(FooInt).Implements(typeof(IFoo)));
Console.WriteLine(typeof(FooInt).Implements(typeof(IFoo<>)));
Console.WriteLine(typeof(FooInt).Implements(typeof(IFoo<int>)));
Console.WriteLine(typeof(FooInt).Implements(typeof(IFoo<string>)));
Console.WriteLine(typeof(FooInt).Implements(typeof(IFoo<,>)));
Console.WriteLine(typeof(FooStringInt).Implements(typeof(IFoo<,>)));
Console.WriteLine(typeof(FooStringInt).Implements(typeof(IFoo<string,int>)));
Console.WriteLine(typeof(Foo<int,string>).Implements(typeof(IFoo<string>)));
}
Il ne devrait y avoir aucun problème:
bool implementsGeneric = (anObject.Implements("IBar`1") != null);
Pour obtenir un crédit supplémentaire, vous pouvez intercepter AmbiguousMatchException si vous souhaitez fournir un paramètre de type générique spécifique avec votre requête IBar.
bool implementsGeneric = (anObject.Implements(typeof(IBar<>).Name) != null);