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

1

Все, что у меня есть из некоторых параметров конфигурации, - это имена моих классов как строки. Все мои классы следуют одному интерфейсу. Но некоторые из них следуют второму другому интерфейсу

Так, например, мои "древовидные" классы будут следовать за интерфейсом IRoots, но некоторые могут иметь разные настройки друг от друга.

coniferousTree : IRoots, IGreenLeafSettings
deciduousTree : IRoots, IGreenLeafSettings
specialtree1 : IRoots, INeonLeafSettings
specialTree2 : IRoots, INeonLeafSettings

Поэтому, когда я сталкиваюсь с именем дерева в своем XML файле, я хочу создать экземпляр точного типа объекта для этого дерева И применить настройки к дереву (как они определены в файле конфигурации)

То, что я застрял, было так. Я говорю об этом узле в XML

<Tree Tree="coniferousTree" Gsetting1="" Gsetting2="" Gsetting3="" />

(где эти три настройки будут свойствами интерфейса настроек, которые реализованы в древовидном объекте)

//first I read the attribute value from XML that indicated the tree object
string treeName = tree.Attribute("Tree").Value;  

//then try and instantiate the object
 Assembly a = Assembly.LoadFile(assemblyPath + @"\Tree.dll");
 var type = a.GetTypes().First(x => x.Name == treeName);
 var myObject = (IRoots)Activator.CreateInstance(type);

Но то, что я действительно хочу вернуть, - это фактический тип объекта, а не тип интерфейса. (потому что я хочу применить к нему настройки)

Если бы я был на этом конкретном узле, я хочу это

var myObject = (**coniferousTree**)Activator.CreateInstance(type);

Но я не могу, потому что заранее не знаю, когда я кодирую, что это тот тип, который мне нужно использовать.

Есть ли хороший способ решить эту проблему, не прибегая к кучам if else, чтобы проверять разные интерфейсы настроек.

  • 1
    Можно ли наследовать все типы деревьев от абстрактного базового класса, имеющего public abstract void LoadSettings(XmlElement element); в теме? (Замените XmlElement на любое tree типов в вашем примере кода)
  • 0
    @ScottChamberlain ScottChamberlain На самом деле это хорошая идея, спасибо. Должен ли это быть абстрактный базовый класс, или я могу просто добавить этот метод в интерфейс IRoot и сделать так, чтобы все мои классы реализовали его по-своему?
Показать ещё 3 комментария
Теги:

1 ответ

1

Если все, что вам нужно сделать, это переместить настройки из файла XML в экземплярный объект, тогда я думаю, что вы ищете Reflection.

var myObject = Activator.CreateInstance(type);

// Substitute code here to retrieve the property name/value pairs from the XML file 
var myProperty = "GSetting1";
var myValue = "ABC";

// See if the requested property actually exists in the class
var oProperty = type.GetProperty(myProperty, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.IgnoreCase | System.Reflection.BindingFlags.Public);
if (oProperty != null)
{
    // If it does, set its value based on what was retrieved from the XML file
    oProperty.SetValue(myObject, myValue, null);
}

Несколько примечаний по этому поводу:

  1. Вы, возможно, потребуется принуждать типы данных, которые считываются из файла XML в тип, соответствующий свойству, но PropertyType свойство на PropertyInfo объекта (возвращенного GetProperty), содержит информацию, чтобы помочь с этим.

  2. Вы также можете использовать метод GetMethod для type для поиска и выполнения методов (т. GetMethod вас может быть метод для установки значений из XML файла).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню