Как передать параметр типа функции generi c из строкового значения? - PullRequest
1 голос
/ 18 марта 2020

Существует универсальная c функция

Result<T> F<T>(int id) { .... }
void F2<T>(Result<T> r) { ... }

и список строк (прочитано с appsettings.json).

List<(string, int)> s = new List<(string, int)> {
    ("int", 10),
    ("string", 21),
    ("DateTime", 31),
    ("int", 20)
    ... }

Как позвонить F с элементами из списка строк?

foreach (var (t, id) in s)
{
    var result = F<???>(id); // need the type from t here
    F2<???>(result);
}

Почему я спросил это:

Оригинальный код имеет список

F<int>(123); 
F<string>(345); 
F<int>(32); 
F<Othertype>(32);
... many more ...

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

Ответы [ 3 ]

3 голосов
/ 18 марта 2020

Краткий ответ F<???> невозможен. Все это происходит во время компиляции. Ближайшая ситуация - использовать «dynamici c», но у вас та же проблема. У вас нет доступа к «элементам типа» напрямую, только по отражению.

var type = Type.GetType("System.Int32");

var obj = Activator.CreateInstance(typeof(F<>).MakeGenericType(type));

Как видите, вы должны хранить типы как полное имя с пространствами имен, но это так.

Другой способ - использовать Dictionary<string, F<T>>, но это заставляет вас обновлять карту каждый раз, когда вы добавляете новый тип для управления. (Если вы используете Dictionary<string, Type>, у вас та же проблема, что и с первым вариантом).

Вы должны учитывать, что если вы хотите вызывать методы, свойства и все, что вам нужно будет сделать с отражением

Редактировать: OTP-решение заключается в динамическом написании кода, его компиляции и загрузке во время выполнения (НЕ ДЕЛАЙТЕ ЭТОГО)

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

2 голосов
/ 18 марта 2020
void F<T>(int id) { .... }
void F(string typeName , int id) 
{ 
    if ( typeName == "int" )
    {
         F<Int>(id)
    }else if ( typeName == "string")
    {
         F<string>(id)
    }
    //... all type
}

foreach (string t in s)
{
    F(t,val);
}
2 голосов
/ 18 марта 2020

Я бы создал словарь для сопоставления от string до Type;

var mappings = new Dictionary<string,Type>(){ { "int", typeof(int) }, ... };

Тогда я бы изменил ваш F<T>(), чтобы вы могли легко вызывать не-обобщенную c версию ;

public static void F<T>(int value) => F(typeof(T), value);
public static void F(Type type, int value){
   ...
}

Остаток теперь должен быть очевиден;

Dictionary<string, int> config = ...
foreach (var t in config)
{
    F(mappings[t.Key], t.Value);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...