[C#] 형식이 특정 일반 인터페이스 형식을 구현하는지 확인하는 방법

다음 유형 정의를 가정하십시오.

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

맹 글링 된 유형 만 사용 가능한 경우 유형이 Foo일반 인터페이스를 구현 하는지 여부를 어떻게 알 IBar<T>수 있습니까?



답변

TcK의 답변을 사용하여 다음 LINQ 쿼리로 수행 할 수도 있습니다.

bool isBar = foo.GetType().GetInterfaces().Any(x =>
  x.IsGenericType &&
  x.GetGenericTypeDefinition() == typeof(IBar<>));


답변

상속 트리를 살펴보고 트리에서 각 클래스의 모든 인터페이스를 찾고 인터페이스가 일반 인지 여부typeof(IBar<>) 를 호출 한 결과 와 비교 해야합니다 . 확실히 조금 아 ful니다.Type.GetGenericTypeDefinition

참조 이 대답 하고 이러한 것들을 더 많은 정보와 코드를.


답변

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


답변

헬퍼 메소드 확장

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

사용법 예 :

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


답변

약간 간단한 버전의 @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));
}

용법:

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


답변

생성 된 일반 인터페이스 유형을 확인해야합니다.

다음과 같은 작업을 수행해야합니다.

foo is IBar<String>

IBar<String>생성 된 형식을 나타 내기 때문 입니다. 경우 때문에이 작업을 수행해야하는 이유는 T수표에 정의되지 뜻 경우, 컴파일러는 모르는 IBar<Int32>IBar<SomethingElse>.


답변

완전히 형식 시스템을 해결하기 위해, 당신이 핸들 재귀, 예를 들어 필요가 있다고 생각 IList<T>: ICollection<T>: IEnumerable<T>당신이 모르는 것이다 않고, IList<int>궁극적으로 구현을 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));

    }