0

私は依存性注入パターンに不慣れで、container.Resolve からクラスの新しいインスタンスを取得する際に問題が発生しています。新しいインスタンスではなく、同じインスタンスを返し続けるだけです。コードについて

public abstract class HObjectBase : Object
{
    private string _name = String.Empty;
    public string Name 
    {
        get
        {
            return this._name;
        }
        set
        {
            if (this._name == string.Empty && value.Length > 0 && value != String.Empty)
                this._name = value;
            else if (value.Length < 1 && value == String.Empty)
                throw new FieldAccessException("Objects names cannot be blank");
            else
                throw new FieldAccessException("Once the internal name of an object has been set it cannot be changed");
        }
    }

    private Guid _id = new Guid();
    public Guid Id 
    {
        get
        {
            return this._id;
        }
        set
        {
            if (this._id == new Guid())
                this._id = value;
            else
                throw new FieldAccessException("Once the internal id of an object has been set it cannot be changed");

        }
    }

    private HObjectBase _parent = null;
    public HObjectBase Parent 
    {
        get
        {
            return this._parent;
        }
        set
        {
            if (this._parent == null)
                this._parent = value;
            else
                throw new FieldAccessException("Once the parent of an object has been set it cannot be changed");
        }
    }
}

public abstract class HZoneBase : HObjectBase
{
    public new HObjectBase Parent
    {
        get
        {
            return base.Parent;
        }
        set
        {
            if (value == null || value.GetType() == typeof(HZoneBase))
            {
                base.Parent = value;
            }
            else
            {
                throw new FieldAccessException("Zones may only have other zones as parents");
            }
        }
    }


    private IHMetaDataStore _store;
    public HZoneBase(IHMetaDataStore store)
    {
        this._store = store;
    }



    public void Save()
    {
        this._store.SaveZone(this);
    }
}

そして、派生クラスは現時点ではダミーですが、ここにあります

public class HZone : HZoneBase
{
    public HZone(IHMetaDataStore store)
        : base(store)
    {
    }
}

これは外部ライブラリであることを意図しているため、すべてにアクセスするための直面クラスがあります

public class Hadrian 
{
    private TinyIoCContainer _container;

    public Hadrian(IHMetaDataStore store)
    {
        this._container = new TinyIoCContainer();
        this._container.Register(store);
        this._container.AutoRegister();
    }

    public HZoneBase NewZone()
    {
        return _container.Resolve<HZoneBase>();
    }

    public HZoneBase GetZone(Guid id)
    {
        var metadataStore = this._container.Resolve<IHMetaDataStore>();
        return metadataStore.GetZone(id);
    }

    public List<HZoneBase> ListRootZones()
    {
        var metadataStore = this._container.Resolve<IHMetaDataStore>();
        return metadataStore.ListRootZones();
    }
}

ただし、Hadrian クラスの GetNewZone() メソッドが同じインスタンスを返し続けるため、テストは失敗しています。

テストコード

[Fact]
public void ListZones()
{
    Hadrian instance = new Hadrian(new MemoryMetaDataStore());
    Guid[] guids = { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() };
    int cnt = 0;
    foreach (Guid guid in guids)
    {
        HZone zone = (HZone)instance.NewZone();
        zone.Id = guids[cnt];
        zone.Name = "Testing" + cnt.ToString();
        zone.Parent = null;
        zone.Save();
        cnt++;
    }

    cnt = 0;
    foreach (HZone zone in instance.ListRootZones())
    {
        Assert.Equal(zone.Id, guids[cnt]);
        Assert.Equal(zone.Name, "Testing" + cnt.ToString());
        Assert.Equal(zone.Parent, null);
    }
}

おそらくパターンに欠けている単純なものだと思いますが、わかりません。助けていただければ幸いです。

4

2 に答える 2

7

まず、問題を実証するために絶対に必要なものにコードを常に単純化してください。MemoryMetaDataStoreコードを実行するには、何が機能するかを推測し、自分で実装する必要がありました。

また、他の人に問題を直接指摘するために、どこどのように失敗したかを教えてください。私が得た例外あなたの問題であり、あなたはアサーションにさえ到達していないことを理解するのに数分を費やしました。

つまりcontainer.Resolve<HZoneBase>()、TinyIoC での自動登録がそのように機能するため、常に同じインスタンスが返されます。抽象化が解決されると、後続の呼び出しに対して常に同じインスタンスが返されます。

これを変更するには、次の行をHadrianコンストラクターに追加します。

this._container.Register<HZoneBase, HZone>().AsMultiInstance();

これにより、 の解決リクエストごとに新しいインスタンスを作成するようコンテナに指示されますHZoneBase

また、Assert 部分に関する Bassetassen の回答は正しいです。

一般に、DI を学びたい場合は、Mark Seemann の優れた本「Dependency Injection in .NET」を読む必要があります。トピック全体が本質的に複雑であるため、簡単に読むことはできませんが、それだけの価値はあり、理解を深めることができます。独学で学ぶよりも数年早く習得できます。

于 2013-07-12T23:57:30.617 に答える