[英]Injecting a resource into an abstract class
我有一个抽象类Shape,并且我有一个Shape用来设置其位置的Canvas对象。 我需要确保所有Shapes都有一个Canvas对象,最好是一个在所有形状中都相同的Canvas对象。
我想到了几个选择:
将画布参数添加到Shape构造函数中(有很多)
在某种程度上可以使抽象Shape获得其Canvas(需要默认值时)
使我所有的形状构造都要经过某种工厂。
哪一个是最好的?
我正在使用C#/ .NET 3.5
拥有由di框架注入的ICanvas公共财产怎么办? 如果确实有很多实现Shape的类,则意味着有很多具有Canvas参数的构造函数,对于属性,您可以在Shape中声明一次并在各处使用它。
您是否想过另一种方式。 我的意思是拥有一个画布对象,然后向其添加形状对象。 这样,您所有的形状对象都有一个共同的参考点,即Canvas。 具有形状集合的画布对象。通过这种方式,您可以执行常见的形状操作,例如在调整画布大小时调整所有形状的大小。
对于依赖注入(DI),最好的默认模式是构造函数注入 (首选),因为它可以轻松实现以确保Shape的不变性。
只需向您的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策略。
我和SM Kamran有类似的想法:您可以在Shape
类中具有Canvas
属性,以指示该形状所属的画布,并在Canvas
类中具有Shapes
集合,以保存形状的集合:
这是一个简单的示例:
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
属性以添加自定义功能。
您还可以创建一个“空/默认画布”单例,并在未将形状分配给实际画布时使用它代替null(只是避免每次检查Shape.Canvas
是否为null)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.