我有几个派生类的抽象类
public abstract class MyObject
{
public string name { get; set; }
public bool IsObject(string pattern);
...
}
public class MyObjectA : MyObject
{
public string name { get { return "MyObjectA"; } set; }
public bool IsObject(string pattern) { ... }
...
}
public class MyObjectB: MyObject
{
public string name { get { return "MyObjectB"; } set; }
public bool IsObject(string pattern) { ... }
...
}
现在,我想有一个功能,基于字符串返回我的特殊类(MyObjectA / MyObectB)。 问题是,我有很多的if / else子句来获取:
public MyObject Create(string pattern)
{
MyObjectA obj = new MyObjectA();
if(obj.IsObject(pattern)
{
return obj;
}
else
{
MyObjectB objb = new MyObjectB();
if(objb.IsObject(pattern);
return objb;
else
...
}
}
这看起来很可怕。 这将是一个更好的方式来做到这一点?
是的,使用反射。
您可以使用Type.GetType得到的实例Type
由串类,然后使用初始化它Activator.CreateInstance
,是这样的:
public MyObject Create(string pattern)
{
Type t = Type.GetType(pattern);
if (t == null) {
throw new Exception("Type " + pattern + " not found.");
}
return Activator.CreateInstance(t);
}
您可以使用Activator.CreateInstance(string, string)
过载也,但这不会直接返回的新实例Type
需要。
您可以使用反射或System.Activator.CreateInstance来创建基于类型或类型名作为字符串的实例。
随着鲁迪·维瑟说,你应该使用反射 。
也让你的类名,你不应该硬编码。 如果您whant使用您的name属性只写
public abstract class MyObject
{
public string name
{
get
{
return this.GetType().Name;
}
}
public bool IsObject(string pattern);
...
}
如果你没有类的名称,只是一些字符串代表它,比你可以检查衍生的所有类MyObject
public MyObject Create(string pattern)
{
Type[] types = Assembly.GetExecutingAssembly().GetTypes();
foreach (Type type in types.Where(t => t.IsSubclassOf(typeof(MyObject))))
{
MyObject obj = (MyObject)Activator.CreateInstance(type);
if (obj.name == pattern)
{
return obj;
}
}
throw new Exception("Type " + pattern + " not found.");
}
有你的陈述的问题很多很好的答案。 不过我建议,您使用工厂模式对于这种类型的需求。
您的“工厂”可能是添加一个静态的简单GetNewMyObject(string pattern)
的方法来你的基类,以及一个protected static Dictionary<string, Type>
。 那么你的派生类可以简单地添加自己的模式+型工厂(在静态构造函数),允许新的派生类被添加到了工厂,而无需修改基类。
这样,你的“模式”字符没有相匹配的类型名称,你也并不需要做任何逻辑模式匹配,你可以这样写:
public static MyObject GetNewMyObject(string pattern)
{
return (MyObject)Activator.CreateInstance(StaticTypeDictionary[pattern]);
}
它可以使用反射像这样做...
public object getInstance(string assemblyName, string className, object[] constructorParameters)
{
System.Reflection.Assembly asm = System.Reflection.Assembly.Load(assemblyName);
return asm.CreateInstance(className, false, System.Reflection.BindingFlags.CreateInstance, null, constructorParameters, null, null);
}
的AssemblyName - 全路径+组装名
的className - 完全限定类名