[英]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.