Подтвердить что ты не робот

Отражение над типовыми ограничениями

В определениях классов и методов можно добавлять ограничения типа, такие как where T : IFoo.

Можно ли отразить эти ограничения с помощью System.Type или MethodInfo? Я ничего не нашел до сих пор; любая помощь будет оценена.

4b9b3361

Ответ 1

Вы можете выполнять итерацию по общим параметрам по типу, и для каждого параметра вы можете запросить типы ограничений.

Вы делаете это, используя:

  • Type.GetGenericArguments Type, чтобы найти общие аргументы типа, т.е. Type<T>, вы найдете T.
  • Type.GetGenericParameterConstraints дает вам базовые типы, с которыми связан каждый такой параметр, вы вызываете это по аргументам, которые вы найдете по приведенному выше методу.

Взгляните на этот код, который вы можете выполнить через LINQPad:

void Main()
{
    Type type = typeof(TestClass<>);
    foreach (var parm in type.GetGenericArguments())
    {
        Debug.WriteLine(parm.Name);
        parm.GetGenericParameterConstraints().Dump();
    }
}

public class TestClass<T>
    where T : Stream
{
}

Вывод:

T

Type [] (1 item)  
typeof (Stream)

Чтобы найти другие ограничения, например new(), вы можете использовать перечисление флагов .GenericParameterAttributes, например:

void Main()
{
    Type type = typeof(TestClass<>);
    foreach (var parm in type.GetGenericArguments())
    {
        Debug.WriteLine(parm.Name);
        parm.GetGenericParameterConstraints().Dump();
        parm.GenericParameterAttributes.Dump();
    }
}

public class TestClass<T>
    where T : new()
{
}

Какие выходы:

T

Type [] (1 item)  
typeof (Stream)

DefaultConstructorConstraint

Ответ 3

Используя ранее найденный System.Type, вы можете использовать GetGenericParameterConstraints().

Здесь отличная статья MSDN на Общие и размышления.

Ответ 4

Lasse answer указывает на соответствующие методы Type. Я использовал его в качестве ссылки при создании этого метода расширения:

public static IList<Tuple<Type, Type[], GenericParameterAttributes>> GetTypeConstraints( this Type type )
{
    return type.GetGenericArguments()
        .Select( t => Tuple.Create( t, t.GetGenericParameterConstraints(), t.GenericParameterAttributes ) )
        .Where( t => t.Item2.Length > 0 || t.Item3 > GenericParameterAttributes.None )
        .ToList();
}

Интересно, что свойство Type.BaseType в общем параметре также возвращает ограничение одного типа.