我可以根据抽象基类中定义的某个属性创建派生类的实例吗?

Posted

技术标签:

【中文标题】我可以根据抽象基类中定义的某个属性创建派生类的实例吗?【英文标题】:Can I create an instance of a derived class based on a certain property defined in my abstract base class? 【发布时间】:2019-03-12 15:59:16 【问题描述】:

基本上我有一个抽象类,我们会说两个属性,一个是抽象类,一个是派生类。

public abstract class BaseClass  
    public string ID  get; set;  
    public abstract string Name  get; ;


public class Class1 : BaseClass  // id would be 1
    public string Name  get  return "Class1 Name"; 


public class Class2 : BaseClass 
    public string Name  get  return "Class2 Name"; 


public class Class3 : BaseClass 
    public string Name  get  return "Class3 Name"; 

然后我的数据层中有一个方法,它基本上返回基类的 ID 列表。我要问的是,如果没有 if 或 switch 语句,我是否可以根据这些 ID 创建 DerivedClass 的新实例?所以……

List<BaseClass> list = new List<BaseClass>();
string id = dataReader["ID"].ToString(); // say this id = 1
list.Add(new BaseClass  ID = id ); // this would be "Class1 Name" and the Class would be Class1

我知道我无法创建抽象类的新实例,因此“new BaseClass()”不起作用,但这是我知道如何解释它的唯一方法。我已经研究过使用反射制作副本或克隆,但不确定它是否真的会做我想要的。这可能不太可能,但我想我会问的。

【问题讨论】:

使用factory method pattern 的变体。创建一个静态方法(在 BaseClass 中或在用作工厂的单独类中),其目的是根据传递给静态方法的某些参数创建并返回具体类型的实例... 谢谢,这就是我要找的东西,而不是在我创建类的任何地方都有逻辑,只需将它放在一个地方。然而,实现是让我绊倒的地方,如果将来要添加新的派生类,我不想更新工厂。 【参考方案1】:

怎么样:

switch(id) 
   case "1": list.Add(new Class1());
   break;
   ...

你也可以使用:

list.Add((BaseClass)Activator.CreateInstance("AssemblyName", "Class"+id));

另见How do I instantiate a class given its string name?

【讨论】:

开关是更好的方法。如果没有必要,你应该避免使用反射。【参考方案2】:

创建一个字典,其中包含与其 id 关联的类型(其值将在您将依赖的字符串属性中):

Dictionary<string, Type> dictOfTypes = new Dictionary<string, Type>();
dictOfTypes.Add("1", typeof(Class1));

然后根据您拥有的 id,您可以从 Dictionary 获取项目,然后创建实例:

string id = "1";
Type classType = dictOfTypes[id];
var instance = Activator.CreateInstance(classType);

【讨论】:

以上是关于我可以根据抽象基类中定义的某个属性创建派生类的实例吗?的主要内容,如果未能解决你的问题,请参考以下文章

抽象类和类成员

使用基类反映派生类的属性

Typescript派生类和抽象类

抽象派生类中的抽象方法覆盖/实现抽象基类的抽象或具体方法。如何以及为啥?

多态和抽象

C#关键字学习