我想知道是否可以使用Dictionary<string, MyType>
作为对象工厂,换句话说,给定一个字符串"Foo"我想要检索我的Foo
类的新实例.
private Dictionary<string, MyType> ClassDic = new Dictionary<string, MyType>()
{
{"Foo", new Foo()},
{"Bar", new Bar()},
//many more
}
Run Code Online (Sandbox Code Playgroud)
我基本上想要做的是替换大量的if语句,然后手动创建对象:
if(line == "Foo") { Stuff.Add(new Foo() { ID = i }; }
if(line == "Bar") { Stuff.Add(new Bar() { ID = i }; }
Run Code Online (Sandbox Code Playgroud)
(Foo
并Bar
从同一基类派生)
这样的事情:
BaseClass myObject;
if(ClassDic.TryGetValue(line, out myObject))
{
Stuff.Add(myObject);
myObject.ID = i;
}
Run Code Online (Sandbox Code Playgroud)
问题出在我的代码中,字典给了我一个对象的相同引用,所以属性覆盖(例如,如果我有300个对象,那么所有300个对象的ID最后都会有相同的ID).
我也对这个问题的其他方法持开放态度.
我想知道是否可以使用Dictionary作为对象工厂,换句话说,给定一个字符串"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() },
}
Run Code Online (Sandbox Code Playgroud)
然后你可以使用:
MyType x = Factories[name]();
Run Code Online (Sandbox Code Playgroud)
话虽如此,如果键实际上只是类的名称,您可以使用反射:
Type type = Type.GetType(name);
MyType x = (MyType) Activator.CreateInstance(type);
Run Code Online (Sandbox Code Playgroud)
请注意,name
此处必须是名称空间限定的类名,因此您可能需要将名称空间添加到您传递的名称之前.它也只会查找当前正在执行的程序集中的类型mscorlib
; 如果需要其他程序集中的类型,则可以传入程序集限定名称,也可以调用Assembly.GetType(name)
相关程序集.