get a class without a lot of if statements

2019-05-11 15:39发布

问题:

I have a certain amount of classes which inherit from an abstract class:

abstract public class baseClass
{
    //logics
}

public class child1 : baseClass
{
}

public class child2 : baseClass
{
}

now I've got some management class which will have to create one of these classes depending on a enum which will have as value the same name so like this:

public enum ClassType
{
    child1,
    child2
}

public class Manager
{
    private List<baseClass> _workers;

    public void Initialize(ClassType type)
    {
        //what logics to put here? (resulting in correctChild)
        _workers.Add(correctChild);
    }
}

I was thinking of typeof but don't know quite how to implement it. Note: in this example it's 2 classes but in the real case it's an arbitrary amount of classes.

回答1:

If you don't need the overhead of attributes and you are running this from the same assembly - you can just use the executing assembly to load the type via reflection. Activator.CreateInstance can take care of building the object for you dynamically.

public class Manager
{
    private List<baseClass> _workers = new List<baseClass>();

    public void Initialize(ClassType type)
    {
        string assemblyName = Assembly.GetExecutingAssembly().GetName().Name;
        Type objType = Type.GetType(string.Format("{0}.{1},{0}", assemblyName, type.ToString()));
        var correctChild =  (baseClass)Activator.CreateInstance(objType);
        _workers.Add(correctChild);
    }
}


回答2:

Have a look at Activator.CreateInstance()

Creates an instance of the type whose name is specified, using the named assembly and default constructor.

so the code would look something like

Activator.CreateInstance(type.ToString(),assemblyName);

I'm actually familiar with such an implementation, i've used it myself. I would also recommend looking into this article that explains how you can actually use attributes on the enum values, to store the actual class names. You can even use it as an extension.

 public static string Description(this Enum enumValue) {
        Type enumType = enumValue.GetType();
        FieldInfo field = enumType.GetField(enumValue.ToString());
        object[] attributes = field.GetCustomAttributes(typeof(DescriptionAttribute), false);
        return attributes.Length == 0 ? enumValue.ToString() : ((DescriptionAttribute)attributes[0]).Description;
}

The code will then look something like

Activator.CreateInstance(classType.Description(), assemblyName);


回答3:

There are many way to differentiate between types.

you can use the is operator

var o = ...;
if (o is Child1) {}

or you could use the as operator

var child = o as Child1;
if (child != null) {}

or what you described yourself already, the typeof operator.

What I am sensing though, is that if you have a strong need for type casting, there might be something else at hand. Maybe you can solve your problem by Polymorphism. Then you don't have to distinguish between all the different types in lengthy if-else or case-switch constructions, but you can delegate the 'different behavior' to your subclasses.



回答4:

If you dont want to use if statements, can you use case statements? like:

public class Manager
{
    private List<baseClass> _workers;

    public void Initialize(ClassType type)
    {
        switch (type)
        {
            case child1:
              _workers.Add(correctChild);
              break;
            case child2:
              _workers.Add(correctChild);
              break;
        }
    }
}


标签: c# class xna