[c#] Come determinare se un tipo implementa un tipo di interfaccia generico specifico



Answers

Devi passare attraverso l'albero di ereditarietà e trovare tutte le interfacce per ogni classe nell'albero e confrontare typeof(IBar<>) con il risultato di chiamare Type.GetGenericTypeDefinition se l'interfaccia è generica. È tutto un po 'doloroso, certamente.

Vedi questa risposta e questi per maggiori informazioni e codice.

Question

Assumi le seguenti definizioni di tipi:

public interface IFoo<T> : IBar<T> {}
public class Foo<T> : IFoo<T> {}

Come faccio a sapere se il tipo Foo implementa l'interfaccia generica IBar<T> quando è disponibile solo il tipo storpiato?




Sto usando una versione leggermente più semplice del metodo di estensione @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));
}

Uso:

    if (!featureType.Implements<IFeature>())
        throw new InvalidCastException();



Per affrontare completamente il sistema di tipi, penso che sia necessario gestire la ricorsione, ad esempio IList<T> : ICollection<T> : IEnumerable<T> , senza il quale non si saprebbe che IList<int> implementa infine IEnumerable<> .

    /// <summary>Determines whether a type, like IList&lt;int&gt;, implements an open generic interface, like
    /// IEnumerable&lt;&gt;. 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));

    }



Come estensione del metodo di supporto

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);
}

Esempio di utilizzo:

var testObject = new Dictionary<int, object>();
result = testObject.GetType().Implements(typeof(IDictionary<int, object>)); // true!



Metodo per verificare se il tipo eredita o implementa un tipo generico:

   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));
    }



Links