[英]Get class by string value
我有一个带有一些派生类的抽象类
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-clause来得到它:
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
...
}
}
这看起来很糟糕。 什么是更好的方法来做到这一点?
是的,使用Reflection。
您可以使用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
的新实例。
您可以使用Reflection或System.Activator.CreateInstance基于Type或TypeName创建一个实例作为字符串。
正如Rudi Visser所说,你应该使用反射 。
另外,为了获得您的班级名称,您不应该对其进行硬编码。 如果你想使用你的名字属性只是写
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>
。 然后,派生类可以简单地将它们的模式+类型添加到工厂(在静态构造函数中),从而允许将新的派生类添加到工厂而无需修改基类。
这样你的'pattern'字符串就不必匹配类型名称,你也不需要做任何逻辑模式匹配,因为你可以编写:
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 - 完全限定的类名
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.