将资源注入抽象类

时间:2009-10-05 10:07:31

标签: c# oop dependency-injection

我有一个抽象类Shape,我有一个Canvas用来设置其位置的Canvas对象。我需要确保所有Shapes都有一个Canvas对象,最好是一个Canvas对象,它与所有形状都是一样。

我想到了几个选择:

  • 将canvas参数添加到Shape构造函数(有很多)

  • 在某种地方抽象Shape获取其画布(当需要默认值时)

  • 让我所有的造型都经过某种工厂。

哪一个最好?

我正在使用C#/ .NET 3.5

4 个答案:

答案 0 :(得分:0)

如果拥有由di framework注入的ICanvas公共属性呢? 如果你真的有很多实现Shape的类,那就意味着很多带有Canvas参数的构造函数,对于你在Shape中声明它一次并在任何地方使用它的属性。

答案 1 :(得分:0)

你有没有想过相反的方式。我的意思是有一个画布对象,然后添加形状对象。这样,所有形状对象都有一个共同的参考点,即Canvas。具有形状集合的画布对象。这样,您可以对形状执行常用操作,例如在画布调整大小时调整所有形状的大小。

答案 2 :(得分:0)

对于依赖注入(DI),最好的默认模式是构造函数注入(您的第一个选项),因为它可以轻松实现以确保您的Shapes不变量。

只需在您的Shape ctor中添加一个Guard子句,如下所示:

private readonly Canvas canvas;

protected Shape(Canvas canvas)
{
    if(canvas == null)
    {
        throw new ArgumentNullException("canvas");
    }
    this.canvas = canvas;
}

这确保了canvas字段始终可用且从不 null。

您可以通过其他方式实现此属性,但Constructo Injection是迄今为止确保不变量的最简单方法,因此除非我有其他需求,否则我总是选择它作为我的默认DI策略。

答案 3 :(得分:0)

我有与SM Kamran类似的想法:您可以在Canvas类中拥有Shape属性,以指示该形状所属的画布,以及Shapes集合中的Canvas你的interface ICanvas { // It's a good thing to use an interface // in this phase. It will allow you greater // freedom later. } class Canvas : ICanvas { private Shape.ShapeCollection _shapes; public Collection<Shape> Shapes { get { return _shapes; } } public Canvas() { _shapes = new Shape.ShapeCollection(this); } } class Shape { public class ShapeCollection : Collection<Shape> { private readonly ICanvas _parent; public ShapeCollection(ICanvas parent) { _parent = parent; } protected override void InsertItem(int index, Shape item) { item._canvas = _parent; base.InsertItem(index, item); } protected override void RemoveItem(int index) { this[index]._canvas = null; base.RemoveItem(index); } protected override void SetItem(int index, Shape item) { RemoveAt(index); InsertItem(index, item); } protected override void ClearItems() { while (this.Count != 0) this.RemoveAt(this.Count - 1); } } private ICanvas _canvas; public ICanvas Canvas { get { return _canvas; } } } 类来保存一组形状:

这是一个简单的例子:

Shape.Canvas

通过向画布添加形状,Canvas canvas = new Canvas(); Shape circle = new Shape(); canvas.Shapes.Add(circle); 属性将自动更新:

ShapeCollection

请注意,Shape_canvas内的嵌套类,因为它是设置私有Collection<Shape>属性的唯一方法。

通用集合(如InsertItem)通常用于类似问题,因为您可以覆盖其RemoveItem / Shape.Canvas属性,以便在更改集合时添加自定义功能。

您还可以创建“空/默认画布”单例,并在未将形状分配给真实画布时使用它而不是null(只是为了避免每次都检查{{1}}是否为空)。