답변:
몇 가지 선택 사항이 있습니다.
typeof(IMyInterface).IsAssignableFrom(typeof(MyType))
typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface))
일반적인 인터페이스의 경우 조금 다릅니다.
typeof(MyType).GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMyInterface<>))
IsAssignableFrom
거꾸로 논쟁을하는 것은 쉬운 일이었습니다 . 나는 GetInterfaces
지금 갈 것이다 : p
IsAssignableFrom(t1)
변형은 GetInterfaces().Contains(t2)
내 코드에 비해 약 3 배 빠릅니다 .
typeof(MyType).GetInterface(nameof(IMyInterface)) != null
더 나은 유형 안전 및 리팩토링을 수행 할 수 있습니다 .
typeof(IMyInterface).IsAssignableFrom(typeof(MyType));
typeof(IMyInterface).IsAssignableFrom(someclass.GetType());
또는
typeof(IMyInterface).IsAssignableFrom(typeof(MyType));
someclass is IMyInterface
반영 비용을 포함하지 않는 것입니다. 따라서 잘못된 것은 아니지만 이상적인 방법은 아닙니다.
is
상속 계층 구조의 양방향으로 IsAssignableFrom
검사 하는 반면 위쪽으로 만 검사합니다. 또한 객체의 인스턴스가 있으면 IsInstanceOfType
(위쪽으로 만) 호출해야합니다 .
public static bool ImplementsInterface(this Type type, Type ifaceType)
{
Type[] intf = type.GetInterfaces();
for(int i = 0; i < intf.Length; i++)
{
if(intf[ i ] == ifaceType)
{
return true;
}
}
return false;
}
세 가지 이유로 이것이 올바른 릴리스라고 생각합니다.
난 그냥했다:
public static bool Implements<I>(this Type source) where I : class
{
return typeof(I).IsAssignableFrom(source);
}
나는 말할 수 있었으면 where I : interface
하지만 interface
일반적인 매개 변수 제약 조건은 아닙니다. class
최대한 가깝습니다.
용법:
if(MyType.Implements<IInitializable>())
MyCollection.Initialize();
나는 Implements
그것이 더 직관적이기 때문에 방금 말했다 . 나는 항상 IsAssignableFrom
플립 플롭된다.
return typeof(I).IsInterface && typeof(I).IsAssignableFrom(source);
메소드의 '잘못된'사용법에 대해 false를 리턴 할 수 있습니다 . 인터페이스 유형 대신 클래스 유형으로 사용하면 type-parameter가 인터페이스가 아닌 경우 예외가 발생합니다. 파생 클래스 '구현물'이 부모라고 주장 할 수 있지만 ...
최적의 성능을 위해 Jeff의 답변 수정 (Pierre Arnaud의 성능 테스트 덕분에) :
var type = typeof(MyType);
var implementsInterface = typeof(IMyInterface).IsAssignableFrom(type) && type.IsClass;
지정된 인터페이스를 구현하는 모든 유형을 찾으려면 다음을 수행하십시오 Assembly
.
var implementations = typeof(TypeInTargetAssembly).Assembly.GetTypes()
.Where(t => typeof(IMyInterface).IsAssignableFrom(t) && t.IsClass);
다른 사람이 이미 언급 한 것처럼 : Benjamin Apr 10 '13 at 22:21 "
주의를 기울이지 않고 IsAssignableFrom에 대한 인수를 거꾸로 얻는 것이 쉬웠습니다. 이제 GetInterfaces를 사용하겠습니다. p –
또 다른 방법은 "가장 일반적인"사고 방식을 어느 정도 충족시키는 짧은 확장 방법을 만드는 것입니다. (그리고 이것은 개인의 취향에 따라 약간 "보다 자연스럽게"만드는 개인적 선택이 거의 없다는 데 동의했습니다. ) :
public static class TypeExtensions
{
public static bool IsAssignableTo(this Type type, Type assignableType)
{
return assignableType.IsAssignableFrom(type);
}
}
그리고 좀 더 일반적인 것이 아닌 이유는 무엇입니까?
public static class TypeExtensions
{
public static bool IsAssignableTo(this Type type, Type assignableType)
{
return assignableType.IsAssignableFrom(type);
}
public static bool IsAssignableTo<TAssignable>(this Type type)
{
return IsAssignableTo(type, typeof(TAssignable));
}
}
나는 그것이 훨씬 자연 스럽지만 다시 한 번 매우 개인적인 의견의 문제라고 생각합니다.
var isTrue = michelleType.IsAssignableTo<IMaBelle>();
Boolean
=> bool
(내가 어렸을 때 코딩의 일부 엄격한 "공상"규칙을 가지고하는 데 사용 왜하지 않습니다).
유형이나 인스턴스가있는 경우 특정 인터페이스를 지원하는지 쉽게 확인할 수 있습니다.
객체가 특정 인터페이스를 구현하는지 테스트하려면
if(myObject is IMyInterface) {
// object myObject implements IMyInterface
}
유형이 특정 인터페이스를 구현하는지 테스트하려면 다음을 수행하십시오.
if(typeof(IMyInterface).IsAssignableFrom(typeof(MyType))) {
// type MyType implements IMyInterface
}
일반 객체를 가지고 있고 캐스팅하고 인터페이스를 구현하고 있는지 확인하려는 경우 코드는 다음과 같습니다.
var myCastedObject = myObject as IMyInterface;
if(myCastedObject != null) {
// object myObject implements IMyInterface
}
이를 검색하는 사람은 다음 확장 방법이 유용 할 수 있습니다.
public static class TypeExtensions
{
public static bool ImplementsInterface(this Type type, Type @interface)
{
if (type == null)
{
throw new ArgumentNullException(nameof(type));
}
if (@interface == null)
{
throw new ArgumentNullException(nameof(@interface));
}
var interfaces = type.GetInterfaces();
if (@interface.IsGenericTypeDefinition)
{
foreach (var item in interfaces)
{
if (item.IsConstructedGenericType && item.GetGenericTypeDefinition() == @interface)
{
return true;
}
}
}
else
{
foreach (var item in interfaces)
{
if (item == @interface)
{
return true;
}
}
}
return false;
}
}
xunit 테스트 :
public class TypeExtensionTests
{
[Theory]
[InlineData(typeof(string), typeof(IList<int>), false)]
[InlineData(typeof(List<>), typeof(IList<int>), false)]
[InlineData(typeof(List<>), typeof(IList<>), true)]
[InlineData(typeof(List<int>), typeof(IList<>), true)]
[InlineData(typeof(List<int>), typeof(IList<int>), true)]
[InlineData(typeof(List<int>), typeof(IList<string>), false)]
public void ValidateTypeImplementsInterface(Type type, Type @interface, bool expect)
{
var output = type.ImplementsInterface(@interface);
Assert.Equal(expect, output);
}
}
정답은
typeof(MyType).GetInterface(nameof(IMyInterface)) != null;
하나,
typeof(MyType).IsAssignableFrom(typeof(IMyInterface));
다음 코드가 string 및 IConvertible과 함께 표시되므로 잘못된 결과를 반환 할 수 있습니다.
static void TestIConvertible()
{
string test = "test";
Type stringType = typeof(string); // or test.GetType();
bool isConvertibleDirect = test is IConvertible;
bool isConvertibleTypeAssignable = stringType.IsAssignableFrom(typeof(IConvertible));
bool isConvertibleHasInterface = stringType.GetInterface(nameof(IConvertible)) != null;
Console.WriteLine($"isConvertibleDirect: {isConvertibleDirect}");
Console.WriteLine($"isConvertibleTypeAssignable: {isConvertibleTypeAssignable}");
Console.WriteLine($"isConvertibleHasInterface: {isConvertibleHasInterface}");
}
결과 :
isConvertibleDirect: True
isConvertibleTypeAssignable: False
isConvertibleHasInterface: True
IsAssignableFrom
. 벤자민과 Ehouarn이 경고 한 것처럼.
일반 인터페이스가 있으면 IMyInterface<T>
항상 다음을 반환합니다 false
.
typeof(IMyInterface<>).IsAssignableFrom(typeof(MyType)) /* ALWAYS FALSE */
이것은 작동하지 않습니다 :
typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface<>)) /* ALWAYS FALSE */
그러나, MyType
구현 IMyInterface<MyType>
이 작품 반환 true
:
typeof(IMyInterface<MyType>).IsAssignableFrom(typeof(MyType))
그러나 T
런타임에 type 매개 변수 를 알지 못할 수 있습니다. 다소 해키 솔루션은 다음과 같습니다.
typeof(MyType).GetInterfaces()
.Any(x=>x.Name == typeof(IMyInterface<>).Name)
Jeff의 솔루션은 약간 덜 해킹 적입니다.
typeof(MyType).GetInterfaces()
.Any(i => i.IsGenericType
&& i.GetGenericTypeDefinition() == typeof(IMyInterface<>));
다음 Type
은 모든 경우에 작동 하는 확장 방법입니다 .
public static class TypeExtensions
{
public static bool IsImplementing(this Type type, Type someInterface)
{
return type.GetInterfaces()
.Any(i => i == someInterface
|| i.IsGenericType
&& i.GetGenericTypeDefinition() == someInterface);
}
}
(위에서 linq를 사용하는데, 이는 아마도 루프보다 느릴 것입니다.)
그런 다음 다음을 수행 할 수 있습니다.
typeof(MyType).IsImplementing(IMyInterface<>)