簡體   English   中英

將資源注入抽象類

[英]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);

請注意, ShapeCollectionShape內的嵌套類,因為它是設置私有_canvas屬性的唯一方法。

通用集合(例如Collection<Shape> )通常用於類似的問題,因為在更改集合時,您可以覆蓋它們的InsertItem / RemoveItem屬性以添加自定義功能。

您還可以創建一個“空/默認畫布”單例,並在未將形狀分配給實際畫布時使用它代替null(只是避免每次檢查Shape.Canvas是否為null)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM