Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 按字符串值获取类_C#_.net_Abstract Class - Fatal编程技术网

C# 按字符串值获取类

C# 按字符串值获取类,c#,.net,abstract-class,C#,.net,Abstract Class,我有一个抽象类和几个派生类 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 I

我有一个抽象类和几个派生类

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
            ...
    }
}
那看起来太糟糕了。有什么更好的方法可以做到这一点?

您可以使用反射,或者根据类型或类型名创建一个实例作为字符串。

是的,使用反射

您可以通过字符串获取类的
类型
的实例,然后使用
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)
重载,但这不会直接返回所需类型的
新实例。

如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.");
}

它可以通过像这样的反射来完成

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

对于您提出的问题,有许多很好的答案。然而,我建议您使用工厂模式来满足这类需求

您的“工厂”可以非常简单,只需向基类添加一个静态
GetNewMyObject(字符串模式)
方法,以及一个受
保护的静态字典。然后,您的派生类可以简单地将其模式+类型添加到工厂(在静态构造函数中),从而允许在不修改基类的情况下向工厂添加新的派生类

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

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

这只是一个例子。名称字符串与类的名称不完全相同,但我可以将其转换为。