2014-11-29 1 views
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

Возможно, что все типы деревьев наследуются от абстрактного базового класса, который имеет «публичный абстрактный void LoadSettings (элемент XmlElement);' на нем? (Замените 'XmlElement' любым типом' tree' в вашем примере кода) –

+0

@ScottChamberlain На самом деле это хорошая идея, спасибо. Должен ли он быть абстрактным базовым классом, или я могу просто добавить этот метод в интерфейс IRoot и все его классы реализовать его по-своему? – erotavlas

+0

Метод в «IRoot» будет работать, я предлагаю отдельный класс/интерфейс, потому что я думал, что «IRoot» был для корней деревьев. И я предложил только абстрактный базовый класс по интерфейсу, чтобы заставить все различные типы деревьев реализовать его, но он легко может быть частью одного из ваших существующих интерфейсов. –

ответ

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 object (возвращается GetProperty), содержит информацию, которая поможет в этом.

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

Смежные вопросы