Попробуйте этот код
static bool IsSubclassOfRawGeneric(Type generic, Type toCheck) {
while (toCheck != null && toCheck != typeof(object)) {
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
if (generic == cur) {
return true;
}
toCheck = toCheck.BaseType;
}
return false;
}
Вот немного метода, который я создал для проверки, что объект получен из определенного типа. Работает отлично для меня!
internal static bool IsDerivativeOf(this Type t, Type typeToCompare)
{
if (t == null) throw new NullReferenceException();
if (t.BaseType == null) return false;
if (t.BaseType == typeToCompare) return true;
else return t.BaseType.IsDerivativeOf(typeToCompare);
}
Код JaredPar работает, но только на один уровень наследования. Для неограниченных уровней наследования используйте следующий код
public bool IsTypeDerivedFromGenericType(Type typeToCheck, Type genericType)
{
if (typeToCheck == typeof(object))
{
return false;
}
else if (typeToCheck == null)
{
return false;
}
else if (typeToCheck.IsGenericType && typeToCheck.GetGenericTypeDefinition() == genericType)
{
return true;
}
else
{
return IsTypeDerivedFromGenericType(typeToCheck.BaseType, genericType);
}
}
(Повторно отправленный из-за крупной перезаписи)
ответ кода JaredPar является фантастическим, но у меня есть подсказка, которая сделала бы его ненужным, если Ваши универсальные типы не основаны на параметрах типа значения. Я был одержим тем, почему оператор, не работал бы, таким образом, я также зарегистрировал результаты своего экспериментирования для дальнейшего использования. Улучшите этот ответ для дальнейшего улучшения его ясности.
, Если Вы удостоверяетесь, что Ваша реализация GenericClass наследовалась абстрактному неуниверсальному базовому классу, такому как GenericClassBase, Вы могли задать тот же вопрос без любой проблемы вообще как это:
typeof(Test).IsSubclassOf(typeof(GenericClassBase))
<час> Мое тестирование указывает, что IsSubclassOf () не работает над универсальными типами без параметров такой как [1 116]
typeof(GenericClass<>)
, тогда как это будет работать с [1 117]
typeof(GenericClass<SomeType>)
Поэтому, следующий код будет работать на любую деривацию GenericClass<>, принимая Вас готовы протестировать на основе SomeType:
typeof(Test).IsSubclassOf(typeof(GenericClass<SomeType>))
единственное время я могу предположить, что Вы хотели бы протестировать GenericClass<> находится в сменном сценарии платформы.
<час> Во время проектирования, которое C# не позволяет использованию дженериков без параметров, потому что они - по существу не полный тип CLR в той точке. Поэтому необходимо объявить, что универсальные переменные с параметрами, и именно поэтому "являются" оператором, так мощно для работы с объектами. Кстати, оператор, также не может оценить универсальные типы без параметров.
оператор, протестирует всю цепочку наследования, включая интерфейсы.
Так, приведенный пример любого объекта, следующий метод добьется цели:
bool IsTypeof<T>(object t)
{
return (t is T);
}
Это - вид избыточных, но я полагал, что буду идти вперед и визуализировать его для всех.
, Учитывая [1 124]
var t = new Test();
следующие строки кода возвратили бы true:
bool test1 = IsTypeof<GenericInterface<SomeType>>(t);
bool test2 = IsTypeof<GenericClass<SomeType>>(t);
bool test3 = IsTypeof<Test>(t);
, С другой стороны, если Вы хотите что-то характерное для GenericClass, Вы могли бы сделать его более конкретным, я предполагаю, как это:
bool IsTypeofGenericClass<SomeType>(object t)
{
return (t is GenericClass<SomeType>);
}
Тогда Вы протестировали бы как это:
bool test1 = IsTypeofGenericClass<SomeType>(t);
Type _type = myclass.GetType();
PropertyInfo[] _propertyInfos = _type.GetProperties();
Boolean _test = _propertyInfos[0].PropertyType.GetGenericTypeDefinition()
== typeof(List<>);
Это может быть излишним, но я использую методы расширения, подобные следующим. Они проверяют интерфейсы, а также подклассы. Он также может возвращать тип, имеющий указанное универсальное определение.
Например, для примера в вопросе он может проверять общий интерфейс, а также универсальный класс. Возвращенный тип можно использовать с GetGenericArguments
, чтобы определить, что общий тип аргумента - «SomeType».
/// <summary>
/// Checks whether this type has the specified definition in its ancestry.
/// </summary>
public static bool HasGenericDefinition(this Type type, Type definition)
{
return GetTypeWithGenericDefinition(type, definition) != null;
}
/// <summary>
/// Returns the actual type implementing the specified definition from the
/// ancestry of the type, if available. Else, null.
/// </summary>
public static Type GetTypeWithGenericDefinition(this Type type, Type definition)
{
if (type == null)
throw new ArgumentNullException("type");
if (definition == null)
throw new ArgumentNullException("definition");
if (!definition.IsGenericTypeDefinition)
throw new ArgumentException(
"The definition needs to be a GenericTypeDefinition", "definition");
if (definition.IsInterface)
foreach (var interfaceType in type.GetInterfaces())
if (interfaceType.IsGenericType
&& interfaceType.GetGenericTypeDefinition() == definition)
return interfaceType;
for (Type t = type; t != null; t = t.BaseType)
if (t.IsGenericType && t.GetGenericTypeDefinition() == definition)
return t;
return null;
}
JAREDPAR,
Это не сработало для меня, если я пройдут тип (тип <>) как Tocheck. Вот что я изменил.
static bool IsSubclassOfRawGeneric(Type generic, Type toCheck) {
while (toCheck != typeof(object)) {
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
if (cur.IsGenericType && generic.GetGenericTypeDefinition() == cur.GetGenericTypeDefinition()) {
return true;
}
toCheck = toCheck.BaseType;
}
return false;
}