#c# #generics #reflection
#c# #обобщения #отражение
Вопрос:
Возможно ли получить во время выполнения тип универсального класса, который имеет переменное количество параметров типа?
То есть, на основе числа, можем ли мы получить тип кортежа с таким количеством элементов?
Type type = Type.GetType("System.Tuple<,>");
Ответ №1:
Способ записать это
Type generic = Type.GetType("System.Tuple`2");
Формат обобщенных типов прост:
"Namespace.ClassName`NumberOfArguments"
` — это символ 96. (ALT 96).
Однако я бы избегал использования строк, это медленнее, чем использование typeof или, что лучше, поиска по массиву. Я бы предоставил хорошую статическую функцию, которая в тысячу раз быстрее…
private static readonly Type[] generictupletypes = new Type[]
{
typeof(Tuple<>),
typeof(Tuple<,>),
typeof(Tuple<,,>),
typeof(Tuple<,,,>),
typeof(Tuple<,,,,>),
typeof(Tuple<,,,,,>),
typeof(Tuple<,,,,,,>),
typeof(Tuple<,,,,,,,>)
};
public static Type GetGenericTupleType(int argumentsCount)
{
return generictupletypes[argumentsCount];
}
Комментарии:
1. Хах, я видел, как они были названы в IL, что я был достаточно глуп, чтобы пропустить это, когда отражение безумно! Спасибо!
2. 🙂 нет, вы не были глупы, это противоречит здравому смыслу, я согласен с вами.
3. Что касается оптимизации, вы, вероятно, правы. В настоящее время я пишу компилятор, который может иметь дело с несколькими универсальными классами, но предоставление таблиц поиска для общих типов может быть весьма полезным
Ответ №2:
Попробуйте это:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;
public class MainClass
{
public static void Main()
{
PrintTypeParams(typeof(Tuple<int, double, string>));
}
private static void PrintTypeParams(Type t)
{
Console.WriteLine("Type FullName: " t.FullName);
Console.WriteLine("Number of arguments: " t.GetGenericArguments().Length);
Console.WriteLine("List of arguments:");
foreach (Type ty in t.GetGenericArguments())
{
Console.WriteLine(ty.FullName);
if (ty.IsGenericParameter)
{
Console.WriteLine("Generic parameters:");
Type[] constraints = ty.GetGenericParameterConstraints();
foreach (Type c in constraints)
Console.WriteLine(c.FullName);
}
}
}
}
Вывод:
Type FullName: System.Tuple`3[[System.Int32, mscorlib, Version=4.0.0.0, Culture=
neutral, PublicKeyToken=b77a5c561934e089],[System.Double, mscorlib, Version=4.0.
0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib,
Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
Number of arguments: 3
List of arguments:
System.Int32
System.Double
System.String