简体   繁体   中英

Adding derived objects to a list dynamically

I have an inheritance tree like so:

BaseType
TypeA : BaseType
TypeB : BaseType
TypeC : BaseType

Each derived object has a variable named objectName that defines that object's name.

I also have an array and a list that both hold the BaseType objects as well as any objects derived from BaseType . The array has objects stored in it upon being created, meanwhile the list is empty for future use:

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

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

I also have a method that is used to add an object that is in the array to the list:

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());
    }
}

How can I avoid having to use all of those if commands? At one point I tried:

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

Which did not work. So how can I go about doing something like this? The objects are constantly growing and I don't want to have to put an if for every derived object I add. I should also mention, not sure if this will have any bearing on the solution, I've been using folders to organize the .cs files. So I have all of the derived classes in a folder named "Types" so to create a new instance of that object I have to type:

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

well, the first thing I see is that you're instantiating your items, and not just passing the item in

are you trying to do the following?

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


the reason

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

doesn't work is because itemToAdd is not a type, it's a variable of the type BaseType . you can't use the new keyword on it. it just doesn't make sense.


if you're trying to copy the item, you can do something like the following.

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

You will have to write your own copy method for this part to work.

Why is your AddToList creating new objects instead of adding the itemToAdd? In other words:

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

Also, there is no need to have a string for the type of object. You can get the type of any object by using:

myObj.GetType();

And you can compare the type of an object using typeof :

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

If you really, really must create new objects of the same type as itemToAdd , then you can use Activator.CreateInstance to avoid all those type checks:

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

But I suspect that isn't what you want to do anyway.

Well, you could make a factory to class to create the object you want based on the class type passed in and use it like this:

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

But of course, this just pushes the question down a level (but still improves the readability of the AddToList code).

To do what you're really asking requires, I think, either doing what you have already suggested: if-else chains (or a switch perhaps) to create an instance of the correct type; or using reflection to new up an instance of a dynamically chosen class.

As simple example:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM