Создание производного класса List <T>во время выполнения с использованием отражения - PullRequest
1 голос
/ 12 января 2020

У меня есть шаблон c class MyList<T> : MyBaseClass, IList<T>, который принимает неизвестное количество неизвестных типов элементов.
В другом месте я объявляю некоторые пользовательские списки НО без их создания ( это должен из-за некоторых общих ограничений ):

MyList<MyObjectType1> type1List1, type1List2,... ;
MyList<MyObjectType2> type2List1, type2List2,... ;

Я хотел бы создать эти пользовательские списки во время выполнения, используя отражение:

foreach (FieldInfo field in this.GetType().GetFields())
{
   if (field.FieldType == typeof(MyList<>)) // this condition is **NEVER** passed!
   {
      MyList<>valueToSet = new MyList<>(); // does not work, needs type
      MyList<T>valueToSet = new MyList<T>(); // does not work, there's no T
      MyList<...?...>valueToSet = new MyList<...?...>(); // how can i put here the type?
      field.SetValue(this, valueToSet);
      ...
   }
}

Проблемы, с которыми я столкнулся, заключаются в том, что тип объектов, используемых в каждом из объявленных списков, неизвестен до времени выполнения, я не могу найти выражение для использования в моем коде для создания экземпляра MyList<...?...>valueToSet = new MyList<...?...>(), а также, что удивительно (по крайней мере для меня) выражение if (field.FieldType == typeof(MyList<>)) никогда не проходит.

На всякий случай рекомендуется учитывать, что из-за некоторых зависимостей и ограничений класса я не могу создать интерфейс для MyList<T>.

Спасибо заранее за любую помощь!

РЕДАКТИРОВАТЬ:
Благодаря Mike и Sweeper я мог бы решить полностью эта проблема

Ответы [ 2 ]

3 голосов
/ 12 января 2020

Первая часть заключается в том, что для того, чтобы выполнить сравнение, то, что вы действительно ищете, это сравнение определения типа generi c типа поля. Измените свой оператор if, чтобы использовать GetGenericTypeDefinition, чтобы проверить, что:

if (field.FieldType.IsGenericType && field.FieldType.GetGenericTypeDefinition() == typeof(MyList<>))

Далее вам нужно создать экземпляр типа, который вы не знаете, Activator.CreateInstance обычно является самым простым способом сделать это:

var list = Activator.CreateInstance(field.FieldType);
field.SetValue(this, list);

Теперь я заметил одну вещь: мы устанавливаем поля для текущего объекта. Это немного необычно. Это почему? Разве вы не знаете все эти типы во время компиляции?

0 голосов
/ 12 января 2020

Можно ли использовать MyList<dynamic> в вашем случае?

например,

type1List1 = new List<dynamic>(); 
type1List1.Add(new MyObjectType1()); 
MyObjectType1 element = type1List1.ElementAt(0);

В основном динамический c - это специальный тип, который может иметь любые свойства - эффективно получая некоторые преимущества более свободно набираемого языка, например JavaScript в C#. Вы можете добавить любой объект в свой MyList. Вам просто нужно будет отслеживать типы каждого из них вручную в своем коде и убедиться, что вы знаете, какой тип вы ожидаете, когда вы будете sh использовать их

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/types/using-type-dynamic

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...