#c# #generics
#c# #обобщения
Вопрос:
У меня есть фрагмент кода, где иногда мне нужно создать новый универсальный тип, но с неизвестным количеством универсальных параметров. Например:
public object MakeGenericAction(Type[] types)
{
return typeof(Action<>).MakeGenericType(paramTypes);
}
Проблема в том, что если у меня в массиве более одного типа, то программа завершится сбоем. В краткосрочной перспективе я придумал что-то вроде этого в качестве промежуточного звена.
public object MakeGenericAction(Type[] types)
{
if (types.Length == 1)
{
return typeof(Action<>).MakeGenericType(paramTypes);
}
else if (types.Length ==2)
{
return typeof(Action<,>).MakeGenericType(paramTypes);
}
..... And so on....
}
Это действительно работает, и достаточно просто, чтобы охватить мои сценарии, но это кажется действительно хакерским. Есть ли лучший способ справиться с этим?
Ответ №1:
В таком случае, да:
Type actionType = Expression.GetActionType(types);
Проблема здесь в том, что вы, вероятно, будете использовать DynamicInvoke, который работает медленно.
Action<object[]>
Затем доступ по индексу может превзойти Action<...>
вызов, выполняемый с помощью DynamicInvoke
Комментарии:
1. Красивое, элегантное решение (или, по крайней мере, настолько, насколько могут быть отражающие дженерики)
2. Очень приятно. Что бы произошло, если бы в вашем массиве было более 16 типов? Кроме того, что полиция кода удаляет у вас все электронные устройства.
3. @IndigoDelta винтики выпадут; p
4. Фантастика! Я бы никогда не нашел это самостоятельно. Я должен указать, что там также есть ‘GetFuncType’.
5. @Marc: Хорошая мысль. Кроме того, скрипт сборки, который создает эту часть фреймворка, автоматически проверяет, были ли добавлены новые типы действий, и соответствующим образом регенерирует код, поэтому у нас есть основания полагать, что это продолжит давать хорошие результаты, даже если мы добавим больше типов действий в будущем!
Ответ №2:
Assembly asm = typeof(Action<>).Assembly;
Dictionary<int, Type> actions = new Dictionary<int, Type>;
foreach (Type action in asm.GetTypes())
if (action.Name == "Action" amp;amp; action.IsGenericType)
actions.Add(action.GetGenericArguments().Lenght, action)
затем вы можете использовать actions
словарь, чтобы быстро найти нужный тип:
public Type MakeGenericAction(Type[] types)
{
return actions[types.Lenght].MakeGenericType(paramTypes);
}