Отражение над типовыми ограничениями - PullRequest
18 голосов
/ 25 марта 2011

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

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

Ответы [ 4 ]

22 голосов
/ 25 марта 2011

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

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

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

Посмотрите на этот код, который вы можете запустить через 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
4 голосов
/ 25 марта 2011

Для этого вы можете использовать метод GetGenericParameterConstraints () .

2 голосов
/ 25 марта 2011

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

Вот отличная статья MSDN о Обобщения и отражения .

0 голосов
/ 22 августа 2016

ответ Лассе указывает на соответствующие 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 в универсальном параметре также возвращает ограничение одного типа.

...