我刚接触依赖注入模式,在tinyioc中从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);
}
}我知道这可能是我在模式中遗漏了一些简单的东西,但我不确定,任何帮助都将不胜感激。
发布于 2013-07-13 07:57:31
首先,请始终将代码简化为演示问题所必需的代码,但要提供足够的代码才能真正运行;我必须猜测MemoryMetaDataStore做什么并自己实现它才能运行代码。
另外,请说在哪里失败,和在哪里失败,让其他人直接指出问题所在。我花了几分钟弄清楚,我得到的异常是你的问题,而你甚至没有进入断言。
也就是说,container.Resolve<HZoneBase>()将始终返回相同的实例,因为这就是TinyIoC中自动注册的工作方式-一旦解析了抽象,后续调用总是会返回相同的实例。
要更改这一点,请将以下行添加到Hadrian构造函数中:
this._container.Register<HZoneBase, HZone>().AsMultiInstance();这将告诉容器为HZoneBase的每个解析请求创建一个新实例。
另外,Bassetassen关于断言部分的回答是正确的。
一般来说,如果你想学习依赖注入,你应该读一读Mark Seemann的优秀著作“.NET中的依赖注入”--这不是一本容易读的书,因为整个主题本身就很复杂,但它非常值得,而且会让你比自己学习它快几年。
发布于 2013-07-12 22:37:26
在断言阶段,您不会递增cnt。您还可以在断言中使用实际值作为期望值。这将会令人困惑,因为它说某些东西是预期的,而它实际上是返回的实际值。
断言部分应该是:
cnt = 0;
foreach (HZone zone in instance.ListRootZones())
{
Assert.Equal(guids[cnt], zone.Id);
Assert.Equal("Testing" + cnt.ToString(), zone.Name);
Assert.Equal(null, zone.Parent);
cnt++;
}https://stackoverflow.com/questions/17606404
复制相似问题