通过字符串值获取类(Get class by string value)

2019-08-04 07:33发布

我有几个派生类的抽象类

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
            ...
    }
}

这看起来很可怕。 这将是一个更好的方式来做到这一点?

Answer 1:

是的,使用反射。

您可以使用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需要。



Answer 2:

您可以使用反射或System.Activator.CreateInstance来创建基于类型或类型名作为字符串的实例。



Answer 3:

随着鲁迪·维瑟说,你应该使用反射 。

也让你的类名,你不应该硬编码。 如果您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.");
}


Answer 4:

有你的陈述的问题很多很好的答案。 不过我建议,您使用工厂模式对于这种类型的需求。

您的“工厂”可能是添加一个静态的简单GetNewMyObject(string pattern)的方法来你的基类,以及一个protected static Dictionary<string, Type> 。 那么你的派生类可以简单地添加自己的模式+型工厂(在静态构造函数),允许新的派生类被添加到了工厂,而无需修改基类。

这样,你的“模式”字符没有相匹配的类型名称,你也并不需要做任何逻辑模式匹配,你可以这样写:

public static MyObject GetNewMyObject(string pattern)
{
  return (MyObject)Activator.CreateInstance(StaticTypeDictionary[pattern]);
}


Answer 5:

它可以使用反射像这样做...

    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 - 完全限定类名



文章来源: Get class by string value