是否可以在c#中创建一个构造随机对象的构造函数列表?

时间:2013-03-22 12:23:02

标签: c#

我有几个类都继承自同一个Shape类。当我创建一个新形状时,我希望它是一个随机的形状。我认为这样做的方法是创建一个列表,该列表将保存所有构造函数的链接,当我需要创建一个新形状时,我将从列表中获取一个随机构造函数并使用它来构造我的形状。我试图以最简单的方式创建列表,但是我收到了错误:

List<Action> constList = new List<Action>();
constList.Add(SShape());
constList.Add(OShape());
constList.Add(LShape());

Shape构造函数定义为:

class Shape
{
    public Shape(PlayGrid grid, Color color)
    {
        ...
    }
    ...
}

每个子形状的构造函数定义如下:

class IShape : Shape
{
    public IShape(PlayGrid grid, Color color) : base(grid, color)
    {
    ...
    }
...
}

构造列表的正确方法是什么,以及从列表中使用构造函数的方法是什么?

承包商还需要获得在不同形状之间变化的参数。

6 个答案:

答案 0 :(得分:5)

这个概念可行,您只需要生成委托错误的语法,并且您希望Func<PlayGrid, Color, Shape>不是Action

var constList = new List<Func<PlayGrid, Color, Shape>>();
constList.Add((pg, c) => new SShape(pg, c));

PlayGrid playgrid = /* however you get this */;
Color color = /* however you get this */;
var shape = constList[randomIdx](playgrid, color);

答案 1 :(得分:2)

你可以这样做:

public class ShapeFactory()
{
   //list of shape constructor functions
   private List<Func<Shape>> constructors;

   //static initalizaton of the constructor list
   static ShapeFactory()
   {
      constructors = new List<Func<Shape>>();
      constructors.Add( () => new OShape());
      constructors.Add( () => new SShape());
      constructors.Add( () => new LShape());
      ....
   }

   public static Shape CreateRandomShape()
   {
       int index = ...get random index somehow...
       return constructors[index]();
   }
}

并在代码

中使用它
Shape randomShape = ShapeFactory.CreateRandomShape();

答案 2 :(得分:0)

我相信你想为所有形状创建一个Interface(也许是'IShape'),然后使用factory来实例化它们(此时你可以随机实例化任何实现你的形状的类型) IShape界面。)

答案 3 :(得分:0)

以这种方式创建随机对象的责任不应该是对象本身的行为。我建议你create a factory来管理这个。您的工厂可以生成构造函数调用列表(或预缓存对象),然后在其create方法中提供其中一个。您的工厂应返回构造对象(可能作为接口,如IShape),而不是要调用以创建对象的Actions。这样,如果您的工厂需要注入依赖项或设置其他值,它可以这样做并管理对象的构造。

另外,如果那是.NET Action类,我猜你的Shape类不会继承它,但是从你的问题中我不清楚“我得到错误”是什么。

这是关于在基类中使用GetRandomShape()方法的注释。您不希望这样,因为您的基类知道并依赖于其子类,这违反了OO设计实践。

答案 4 :(得分:0)

您可以将类的类型保存到列表中,并使用Activator.CreateInstance(Type)来获取新实例。

或者您创建一个Shape类型列表,添加每个类的一个实例并使用.Clone()方法获取新实例。

或者您实施了factory pattern

答案 5 :(得分:0)

这是你开始的延续。它使用Reflection来调用构造函数。初始列表是类型列表,而不是操作。

class Program
    {
        static void Main(string[] args)
        {


            //register the types
            List<Type> types = new List<Type>() { typeof(OShape), typeof(PShape), typeof(RShape) };

            // randomly select one
            Type type = types[1];

            // invoke the ctor
            ConstructorInfo ctor = type.GetConstructor(/*optional param for ctor, none in this case*/ new Type[] {} );
            object instance = ctor.Invoke(new object[] {});

            // you can safely cast to Shape
            Shape shape = (Shape)instance; //this is a PShape!

        }
    }

    class Shape
    {
    }

    class OShape : Shape
    {
    }

    class PShape : Shape
    {
    }

    class RShape : Shape
    {
    }
}

接下来要考虑的是如何允许Shape的子类型接收参数。你需要一个工厂模式,即一个知道如何构造其他对象的对象,并将基于 - 例如 - 一个字符串:

Shape s = Factory.GetShape("OShape", new[] object {4});

检查this question