'open'제네릭 형식과 함께 IsAssignableFrom 사용
리플렉션을 사용하여 주어진 기본 클래스에서 상속되는 유형 집합을 찾으려고합니다. 단순한 유형을 알아내는 데 오래 걸리지 않았지만 제네릭에 관해서는 난처합니다.
이 코드의 경우 첫 번째 IsAssignableFrom은 true를 반환하고 두 번째는 false를 반환합니다. 그러나 최종 과제는 잘 컴파일됩니다.
class class1 { }
class class2 : class1 { }
class generic1<T> { }
class generic2<T> : generic1<T> { }
class Program
{
static void Main(string[] args)
{
Type c1 = typeof(class1);
Type c2 = typeof(class2);
Console.WriteLine("c1.IsAssignableFrom(c2): {0}", c1.IsAssignableFrom(c2));
Type g1 = typeof(generic1<>);
Type g2 = typeof(generic2<>);
Console.WriteLine("g1.IsAssignableFrom(g2): {0}", g1.IsAssignableFrom(g2));
generic1<class1> cc = new generic2<class1>();
}
}
그렇다면 하나의 제네릭 유형 정의가 다른 것에서 파생되었는지 런타임에 어떻게 결정합니까?
로부터 또 다른 질문에 대한 답변 :
public static bool IsAssignableToGenericType(Type givenType, Type genericType)
{
var interfaceTypes = givenType.GetInterfaces();
foreach (var it in interfaceTypes)
{
if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType)
return true;
}
if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType)
return true;
Type baseType = givenType.BaseType;
if (baseType == null) return false;
return IsAssignableToGenericType(baseType, genericType);
}
(답이 마음에 들면 코드가 내 것이 아니기 때문에 링크 된 답변을 찬성하십시오.)
게시 한 정확한 코드는 놀라운 결과를 반환하지 않습니다.
이것은 "거짓"이라고 말합니다.
Type g1 = typeof(generic1<>);
Type g2 = typeof(generic2<>);
Console.WriteLine("g1.IsAssignableFrom(g2): {0}", g1.IsAssignableFrom(g2));
이것은 "true"라고 말합니다.
Type g1 = typeof(generic1<class1>);
Type g2 = typeof(generic2<class1>);
Console.WriteLine("g1.IsAssignableFrom(g2): {0}", g1.IsAssignableFrom(g2));
차이점은 개방형 제네릭 유형은 인스턴스를 가질 수 없으므로 하나가 다른 유형에 "할당"되지 않는다는 것입니다.
로부터 문서 :
반환
true
하는 경우c
현재는Type
같은 유형을 표시, 또는 현재이 경우Type
의 상속 계층 구조에c
, 또는 현재이 경우Type
인터페이스가 그c
구현 경우, 또는c
제네릭 형식 매개 변수이며, 전류Type
의 제약 중 하나를 나타냅니다c
.false
이러한 상황에 해당되지 않는 경우, 또는 경우가c
있습니다null
.
이 경우 이러한 조건 중 어느 것도 사실이 아닙니다. 추가 메모가 있습니다.
제네릭 형식 정의는 닫힌 생성 형식에서 할당 할 수 없습니다. 즉, 닫힌 생성 형식
MyGenericList<int>
(MyGenericList(Of Integer)
Visual Basic의 경우)을 형식의 변수에 할당 할 수 없습니다MyGenericList<T>
.
다음의 경우 Konrad Rudolph가 제공 한 메소드를 사용하면 다음과 같이 잘못 될 수 있습니다. IsAssignableToGenericType (typeof (A), typeof (A <>)); // return false
여기에 더 나은 대답이 있다고 생각합니다
public static bool IsAssignableFrom(Type extendType, Type baseType)
{
while (!baseType.IsAssignableFrom(extendType))
{
if (extendType.Equals(typeof(object)))
{
return false;
}
if (extendType.IsGenericType && !extendType.IsGenericTypeDefinition)
{
extendType = extendType.GetGenericTypeDefinition();
}
else
{
extendType = extendType.BaseType;
}
}
return true;
}
자세한 내용 은 C # 제네릭과 함께 IsAssignableFrom 사용을 참조 하세요.
using System;
/**
* Sam Sha - yCoder.com
*
* */
namespace Test2
{
class MainClass
{
public static void Main (string[] args)
{
string a = "ycoder";
Console.WriteLine(a is object);
A aa = new A();
//Console.WriteLine(aa is A<>);//con't write code like this
typeof(A<>).IsAssignableFrom(aa.GetType());//return false
Trace(typeof(object).IsAssignableFrom(typeof(string)));//true
Trace(typeof(A<>).IsAssignableFrom(typeof(A)));//false
AAA aaa = new AAA();
Trace("Use IsTypeOf:");
Trace(IsTypeOf(aaa, typeof(A<>)));
Trace(IsTypeOf(aaa, typeof(AA)));
Trace(IsTypeOf(aaa, typeof(AAA<>)));
Trace("Use IsAssignableFrom from stackoverflow - not right:");
Trace(IsAssignableFrom(typeof(A), typeof(A<>))); // error
Trace(IsAssignableFrom(typeof(AA), typeof(A<>)));
Trace(IsAssignableFrom(typeof(AAA), typeof(A<>)));
Trace("Use IsAssignableToGenericType:");
Trace(IsAssignableToGenericType(typeof(A), typeof(A<>)));
Trace(IsAssignableToGenericType(typeof(AA), typeof(A<>)));
Trace(IsAssignableToGenericType(typeof(AAA), typeof(A<>)));
}
static void Trace(object log){
Console.WriteLine(log);
}
public static bool IsTypeOf(Object o, Type baseType)
{
if (o == null || baseType == null)
{
return false;
}
bool result = baseType.IsInstanceOfType(o);
if (result)
{
return result;
}
return IsAssignableFrom(o.GetType(), baseType);
}
public static bool IsAssignableFrom(Type extendType, Type baseType)
{
while (!baseType.IsAssignableFrom(extendType))
{
if (extendType.Equals(typeof(object)))
{
return false;
}
if (extendType.IsGenericType && !extendType.IsGenericTypeDefinition)
{
extendType = extendType.GetGenericTypeDefinition();
}
else
{
extendType = extendType.BaseType;
}
}
return true;
}
//from stackoverflow - not good enough
public static bool IsAssignableToGenericType(Type givenType, Type genericType) {
var interfaceTypes = givenType.GetInterfaces();
foreach (var it in interfaceTypes)
if (it.IsGenericType)
if (it.GetGenericTypeDefinition() == genericType) return true;
Type baseType = givenType.BaseType;
if (baseType == null) return false;
return baseType.IsGenericType &&
baseType.GetGenericTypeDefinition() == genericType ||
IsAssignableToGenericType(baseType, genericType);
}
}
class A{}
class AA : A{}
class AAA : AA{}
}
포함 된 유형을 비교해야합니다. 참조 : 제네릭 클래스 또는 메서드의 멤버에서 T 유형을 가져 오는 방법은 무엇입니까?
즉, 제네릭 클래스 자체가 아닌 제네릭 클래스에 포함 된 유형이 할당 가능한지 확인해야한다고 생각합니다.
I have a different Approach that resolves this issue, Here are my classes
public class Signal<T>{
protected string Id {get; set;} //This must be here, I use a property because MemberInfo is returned in an array via GetMember() reflection function
//Some Data and Logic And stuff that involves T
}
public class OnClick : Signal<string>{}
Now if I have an instance of type OnClick but I dont know that, and I want to find out if I have an instance of anything which inherits from Signal<> of any type? I do this
Type type = GetTypeWhomISuspectMightBeAGenericSignal();
PropertyInfo secretProperty = type.GetProperty("Id", BindingFlags.NonPublic | BindingFlags.Instance);
Type SpecificGenericType = secretProperty.DeclaringType; //This is the trick
bool IsMyTypeInheriting = SpecificGenericType.IsGenericType && SpecificGenericType.GetGenericTypeDefinition() == typeof(Signal<>); //This way we are getting the genericTypeDefinition and comparing it to any other genericTypeDefinition of the same argument length.
So this works for me, its not recursive, and it uses a trick via a designated property. It has limitations that its hard to write a function that checks assignability for all generics ever. But for a specific type it works
Obviously you need to check if() conditions better and stuff, but these are the Raw lines required to evaluate assignability of a type to its base generic, this way.
Hope this helps
ReferenceURL : https://stackoverflow.com/questions/5461295/using-isassignablefrom-with-open-generic-types
'Development Tip' 카테고리의 다른 글
일부 변경 세트를 수은의 새 분기로 이동하는 방법 (0) | 2020.12.30 |
---|---|
EF Code First에서 내 테이블을 어떻게 단일화합니까? (0) | 2020.12.30 |
Hibernate 오류 :이 클래스의 ID는 save ()를 호출하기 전에 수동으로 할당되어야합니다. (0) | 2020.12.30 |
게터와 세터를 동기화해야합니까? (0) | 2020.12.30 |
XML을 동적 C # 객체로 변환 (0) | 2020.12.30 |