유형이 특정 일반 인터페이스 유형을 구현하는지 확인하는 방법
다음 유형 정의를 가정합니다.
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<>)
방문한 결과.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;
}
}
저는 @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();
도우미 메서드 확장으로
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!
유형 시스템을 완전히 다루기 위해서는 재귀 등을 처리해야 한다고 생각합니다.IList<T>
:ICollection<T>
:IEnumerable<T>
그것이 없었다면 당신은 그것을 알지 못했을 것입니다.IList<int>
궁극적으로 실행합니다.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));
}
일반적인 기본 유형과 인터페이스를 지원하는 확장 방법이 필요한 경우 sduploy의 답변을 확장했습니다.
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);
}
생성된 유형의 일반 인터페이스를 확인해야 합니다.
다음과 같은 작업을 수행해야 합니다.
foo is IBar<String>
왜냐면IBar<String>
생성된 유형을 나타냅니다.당신이 이렇게 해야 하는 이유는 만약에T
당신의 수표에 정의되어 있지 않습니다. 컴파일러는 당신이 의미하는지 모릅니다.IBar<Int32>
또는IBar<SomethingElse>
.
우선public class Foo : IFoo<T> {}
T 대신 클래스를 지정해야 하기 때문에 컴파일하지 않지만, 다음과 같은 작업을 수행한다고 가정합니다.public class Foo : IFoo<SomeClass> {}
그렇다면
Foo f = new Foo();
IBar<SomeClass> b = f as IBar<SomeClass>;
if(b != null) //derives from IBar<>
Blabla();
형식이 일반 형식을 상속하거나 구현하는지 확인하는 방법:
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));
}
다음 확장을 시도하십시오.
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);
}
테스트합니다. 생성합니다.
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 { }
그리고 테스트 방법.
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>)));
}
var genericType = typeof(ITest<>);
Console.WriteLine(typeof(Test).GetInterfaces().Any(x => x.GetGenericTypeDefinition().Equals(genericType))); // prints: "True"
interface ITest<T> { };
class Test : ITest<string> { }
이것은 저에게 효과가 있었습니다.
다음 확장 방법을 추가할 수 있습니다.
public static TypeExtension
{
public static bool IsImplement<T>(this Type type)
{
return type.IsImplement(typeof(T));
}
public static bool IsImplement(this Type type, Type interfaceType)
{
if (!interfaceType.IsInterface)
throw new InvalidOperationException("Only interfaces can be implemented.");
return type.IsAssignableTo(interfaceType) ||
interfaceType.IsGenericType && type.GetInterfaces()
.Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == interfaceType.GetGenericTypeDefinition());
}
}
다음과 같은 문제가 없어야 합니다.
bool implementsGeneric = (anObject.Implements("IBar`1") != null);
IBar 쿼리에 특정 제네릭 유형 매개 변수를 제공하려는 경우 추가 크레딧을 받을 수 있습니다.
언급URL : https://stackoverflow.com/questions/503263/how-to-determine-if-a-type-implements-a-specific-generic-interface-type
'bestsource' 카테고리의 다른 글
의 의 의 (0) | 2023.05.14 |
---|---|
응용 프로그램이 중단 모드에 있음 - 원인을 확인할 수 없음 (0) | 2023.05.14 |
스택을 역방향으로 적용하는 방법은 무엇입니까? (0) | 2023.05.14 |
WPF에 대한 자바의 대답은 무엇입니까? (0) | 2023.05.09 |
Node.js에서 ES6 가져오기를 사용하려면 어떻게 해야 합니까? (0) | 2023.05.09 |