2015-04-15 4 views
1

Интересно, можно ли использовать Dictionary<string, MyType> в качестве фабрики объектов, другими словами, с учетом строки «Foo». Я хочу получить новый экземпляр класса Foo.Использование словаря для создания новых экземпляров объектов

private Dictionary<string, MyType> ClassDic = new Dictionary<string, MyType>() 
{ 
    {"Foo", new Foo()}, 
    {"Bar", new Bar()}, 
    //many more 

} 

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

if(line == "Foo") { Stuff.Add(new Foo() { ID = i }; } 
if(line == "Bar") { Stuff.Add(new Bar() { ID = i }; } 

(Foo и Bar выводим как из того же базового класса)

примерно на следующее:

BaseClass myObject; 
if(ClassDic.TryGetValue(line, out myObject)) 
{ 
    Stuff.Add(myObject); 
    myObject.ID = i; 
} 

проблема в моем коде, словарь дает мне одну и ту же ссылку на объект, поэтому свойства переписываются (например, если у меня есть 300 объектов, все 300 будут иметь тот же ID (последний) в конце).

Я также открыт для других подходов к решению этой проблемы.

+1

Непонятно, что вы просите. Какая картина больше? Чего вы хотите достичь (полное описание)? Это об объектной фабрике или о том, что неправильные идентификаторы в вашем словаре? – DrKoch

+0

Возможно, вам стоит подумать об отражении –

ответ

8

Интересно, можно ли использовать словарь как фабрику объектов, другими словами, задать строку «Foo». Я хочу получить новый экземпляр моего класса Foo.

Учитывая то, что вы хотите создать новый экземпляр, я предложил бы использовать Dictionary<string, Func<MyType>> так:

private static readonly Dictionary<string, Func<MyType>> Factories = 
    new Dictionary<string, Func<MyType>>() 
{ 
    {"Foo",() => new Foo() }, 
    {"Bar",() => new Bar() }, 
} 

Затем вы можете использовать:

MyType x = Factories[name](); 

Сказав, что , если ключ действительно только название класса, вы можете использовать отражение:

Type type = Type.GetType(name); 
MyType x = (MyType) Activator.CreateInstance(type); 

Отметьте, что name должно быть названо классом класса имен, поэтому вам может потребоваться добавить пространство имен к имени, которое вы передадите. Он также будет искать только тип в текущей исполняемой сборке и mscorlib; если вам нужны типы из других сборок, вы можете либо передать имя с квалификацией, либо позвонить Assembly.GetType(name) вместо соответствующей сборки.

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