22

我有一个带有几个派生类的抽象类

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-clauses 来得到它:

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

这看起来很糟糕。有什么更好的方法来做到这一点?

4

5 回答 5

29

是的,使用反射。

您可以使用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所需的新实例。

于 2012-12-19T12:08:12.457 回答
7

您可以使用 Reflection 或System.Activator.CreateInstance根据 Type 或 TypeName 作为字符串创建实例。

于 2012-12-19T12:07:34.530 回答
5

正如 Rudi Visser 所说,您应该使用反射

另外,要获得您的班级名称,您不应对其进行硬编码。如果你想使用你的 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.");
}
于 2012-12-19T12:15:27.560 回答
1

您提出的问题有很多很好的答案。但是,我建议您对这种类型的要求使用工厂模式。

您的“工厂”可以像向GetNewMyObject(string pattern)基类添加静态方法以及protected static Dictionary<string, Type>. 然后您的派生类可以简单地将它们的模式+类型添加到工厂(在静态构造函数中),允许将新的派生类添加到工厂而不修改基类。

这样,您的“模式”字符串不必与类型名称匹配,并且您也不需要进行任何逻辑模式匹配,因为您可以编写:

public static MyObject GetNewMyObject(string pattern)
{
  return (MyObject)Activator.CreateInstance(StaticTypeDictionary[pattern]);
}
于 2012-12-19T22:01:04.707 回答
0

可以像这样使用反射来完成......

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

于 2012-12-19T12:32:14.423 回答