Как я могу использовать объект типа в качестве конкретного типа?

#c# #types

#c# #типы

Вопрос:

Я использую внешнюю библиотеку C #, которая использует generics для своих процессов. Но я хочу использовать его в цикле, который находится во внешнем классе. Моя проблема в том, что я не могу передавать типы между классами.

Вот пример:

Я использую класс SettingsXmlReader для чтения некоторых частей XML-файла. Эти части указаны в конкретных классах:

 SettingsXmlReader settingsXmlReader = new SettingsXmlReader(settingsXmlPath);
settingsXmlReader.AddContainer(typeof(ReleasePathContainer));
settingsXmlReader.AddContainer(typeof(HistoryPathContainer));
(...)
  

Итак, я передал свои конкретные типы в объект settingsXmlReader, но теперь я не могу использовать эти типы следующим способом (поскольку этого требует внешняя библиотека):

 foreach (Type aContainer in containers)
{
    XmlContainerInitializer<aContainer> containerInitializer = new XmlContainerInitializer<aContainer>();
    IBaseContainer container = containerInitializer.InitializeXmlContainer(settingsXmlFile);
}
  
 'aContainer' is a variable but is used like a type
  

Я также попробовал следующий режим:

 SettingsXmlReader settingsXmlReader = new SettingsXmlReader(settingsXmlPath);
settingsXmlReader.AddContainer<ReleasePathContainer>();
settingsXmlReader.AddContainer<HistoryPathContainer>();
  

Но в этом случае я не знаю, как его сохранить или использовать:

 private IList<T> containers;
public void AddContainer<T>()
{
    containers.Add<T>();
}
  

Комментарии:

1. У вас уже есть код, который это делает settingsXmlReader.AddContainer(typeof(ReleasePathContainer)) . Разве вы не можете просто сделать settingsXmlReader.AddContainer(type) ?

2. Если я использую его следующим образом: settingsXmlReader.AddContainer(ReleasePathContainer); я получил следующую ошибку от IntelliSense: ReleasePathContainer — это тип, который недопустим в данном контексте.

3. Как и в вашем цикле foreach (Type aContainer in containers) . Не можете ли вы тогда сделать settingsXmlReader.AddContainer(aContainer); ?

4. typeof(ReleasePathContainer) возвращает вам Type объект, который представляет ReleasePathContainer тип. Вы можете сделать Type type = typeof(ReleasePathContainer); settingsXmlReader.AddContainer(type) , и он делает то же самое, что и settingsXmlReader.AddContainer(typeof(ReleasePathContainer))

5. Вы не можете. Вы можете перейти от generics к Type object ( Type type = typeof(T) ) , но вы не можете вернуться другим путем, не используя отражение. Дженерики являются частью системы строгих типов C #; Type объекты — нет.

Ответ №1:

Если вам действительно нужно использовать этот цикл «AContainer», вы можете избежать ошибки переменной против типа, используя MakeGenericType , что-то вроде этого:

 Type[] typeArgs = new Type[] { aContainer };

Type genericType = typeof(XmlContainerInitializer<>);
Type specificType = genericListType.MakeGenericType(typeArgs);

// This gets you a XmlContainerInitializer of the right type
var containerInitializer = Activator.CreateInstance(specificType);

// You can then try using it dynamically
dynamic d = containerInitalizer;
IBaseContainer container = (IBaseContainer)d.InitializeXmlContainer(settingsXmlFile);

// Or, if XmlContainerInitializer supports some base interface IContainerInitializer ...
var i = (IContainerInitializer)containerInitializer;
IBaseContainer container = i.InitializeXmlContainer(settingsXmlFile);
  

Комментарии:

1. Спасибо за вашу помощь, теперь он работает нормально и динамически. Это то, что я хотел. 🙂