是否可以动态选择多态类

时间:2014-08-11 14:12:36

标签: c# class polymorphism

我正在使用多态来使用基本形状类

定义不同的形状类
public class Shape
{
}

class Circle : Shape
{
}

class Triangle : Shape
{
}

在运行时,我根据变量" thisShape"

创建一个类的实例
Shape myShape;
if (thisShape == "Circle") myShape = new Circle();
if (thisShape == "Triangle") myShape = new Triangle();

这有效,但我觉得应该有办法避免使用多个if。

# Pseudo code
Shape myShape = new {thisShape}();

动态实例是否有单行语法?

2 个答案:

答案 0 :(得分:2)

理论上有,但我不推荐它:你可以使用反射。

Type shapeType = Assembly.GetExecutingAssembly().GetType(thisShape);
Shape myShape = (Shape)Activator.CreateInstance(shapeType);

编辑:

这带来了许多问题,包括性能和安全问题。 有更好的方法来处理这些问题,例如抽象工厂设计模式。

答案 1 :(得分:1)

您应该将其封装到SimpleShapeFactory

如果您不想撰写ifcase,可以创建自己的Attribute(让它命名为ShapeNameAttribute):

[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = false)]
sealed class ShapeNameAttribute : Attribute
{
    #region Constructors

    public ShapeNameAttribute(string name)
    {
        Name = name;
    }

    #endregion // Constructors

    #region Properties

    public string Name
    {
        get;
        set;
    }

    #endregion // Properties
}

然后使用此属性标记所有类:

[ShapeName("Shape")]
public class Shape
{
}

[ShapeName("Circle")]
class Circle : Shape
{
}

[ShapeName("Triangle")]
class Triangle : Shape
{
}

并像这样创建SimpleShapeFactory

static class SimpleShapeFactory
{
    #region Private Members

    public static readonly Type[] _shapes = new Type[]
    {
        typeof(Shape),
        typeof(Circle),
        typeof(Triangle)
    };

    #endregion // Private Members

    #region Methods

    /// <summary>
    /// Creates shape by it's name
    /// </summary>
    /// <param xmlName="name">Name of the shape</param>
    /// <returns>Created shape</returns>
    public static Shape Create(string name)
    {
        foreach(var shape in _shapes)
        {
            var attribute = (ShapeNameAttribute)shape.GetCustomAttributes(typeof(ShapeNameAttribute), true)[0];

            if(attribute.Name == name)
            {
                return (Shape)Activator.CreateInstance(shape);
            }
        }

        throw new ArgumentException("Invalid name");
    }

    #endregion // Methods

}

如果您不想在SimpleShapeFactory中定义允许的类型,当然可以使用反射来确定它们,但

注意:请记住,使用反射可能会导致性能问题。