动态地将派生对象添加到列表中

时间:2012-11-05 19:35:17

标签: c#

我有一个类似的继承树:

BaseType
TypeA : BaseType
TypeB : BaseType
TypeC : BaseType

每个派生对象都有一个名为objectName的变量,用于定义该对象的名称。

我还有一个数组和一个列表,它们都包含BaseType个对象以及从BaseType派生的任何对象。数组在创建时存储了对象,同时列表为空以备将来使用:

BaseType[] arrayA = new BaseType[] { new TypeA(), new TypeB(), new TypeC(), }

List<BaseType> listA = new List<BaseType>;

我还有一个方法用于将数组中的对象添加到列表中:

public void AddToList(BaseType itemToAdd)
{
    if(itemToAdd.objectName == "Type A")
        {
        listA.Add(new TypeA());
    }
    else if(itemToAdd.objectName == "Type B")
        {
        listA.Add(new TypeB());
    }
    else if(itemToAdd.objectName == "Type C")
        {
        listA.Add(new TypeA());
    }
}

如何避免使用所有if命令?有一次我试过了:

public void AddToList(BaseType itemToAdd)
{
    listA.Add( new itemToAdd());
}

哪个不起作用。那么我怎么能做这样的事呢?对象不断增长,我不想为我添加的每个派生对象添加if。我还应该提一下,不确定这是否会对解决方案有任何影响,我一直在使用文件夹来组织.cs文件。所以我将所有派生类都放在一个名为“Types”的文件夹中,以便创建我必须键入的该对象的新实例:

listA.Add(new Types.TypeA());

3 个答案:

答案 0 :(得分:2)

好吧,我看到的第一件事就是你要实例化你的物品,而不只是传递物品

你试图做以下事情吗?

public void AddToList(BaseType itemToAdd)
{
    listA.Add(itemToAdd);
}


原因

public void AddToList(BaseType itemToAdd)
{
    listA.Add( new itemToAdd());
}

不起作用是因为itemToAdd不是类型,它是BaseType类型的变量。您无法在其上使用new关键字。它只是没有意义。


如果您要复制该项目,可以执行以下操作。

public void AddToList(BaseType itemToAdd)
{
    listA.Add(itemToAdd.Copy());
}

您必须为此部分编写自己的复制方法才能正常工作。

答案 1 :(得分:1)

为什么您的AddToList会创建新对象而不是添加itemToAdd?换句话说:

public void AddToList(BaseType itemToAdd)
{
    listA.Add(itemToAdd);
}

此外,不需要为对象类型提供字符串。您可以使用以下方法获取任何对象的类型:

myObj.GetType();

您可以使用typeof来比较对象的类型:

if (myObj.GetType() == typeof(TypeA))

如果真的,那么必须创建与itemToAdd相同类型的新对象,那么您可以使用Activator.CreateInstance来避免所有类型检查:

listA.Add((BaseType)Activator.CreateInstance(itemToAdd.GetType());

但我怀疑这不是你想要做的。

答案 2 :(得分:0)

好吧,你可以根据传入的类类型创建一个工厂来创建你想要的对象,然后像这样使用它:

public void AddToList(BaseType itemToAdd)
{
    listA.Add(ItemFactory.Create(itemToAdd.objectName));
}

但是,当然,这只是将问题推到了一个级别(但仍然提高了AddToList代码的可读性)。

要做你真正要求的事情,我认为,要么做你已经建议的事情:if-else链(或者可能是一个开关)来创建一个正确类型的实例;或使用反射来新建动态选择的类的实例。

简单的例子:

BaseType Create(BaseType source)
{
    var constructor = source.GetType().GetConstructor(new Type[0]);
    return constructor.Invoke(new object[0]) as BaseType;
}