如果我有以下设置,当在同一个上下文中创建对象时,如何配置我的容器以使用相同的数据库
public class Database { }
public interface IRepository { Database Database { get; } }
public interface IFooRepository : IRepository { }
public interface IBarRepository : IRepository { }
public class FooRepository : IFooRepository
{
public Database Database { get; private set; }
public FooRepository(Database database) { this.Database = database; }
}
public class BarRepository : IBarRepository
{
public Database Database { get; private set; }
public BarRepository(Database database) { this.Database = database; }
}
public class Consumer
{
public IFooRepository fooRepository { get; private set; }
public IBarRepository barRepository { get; private set; }
public Consumer(IFooRepository fooRepository, IBarRepository barRepository)
{
this.fooRepository = fooRepository;
this.barRepository = barRepository;
}
}
[TestClass]
public class ConfigurationTest
{
private IWindsorContainer container;
[TestMethod]
public void SameDatabaseIsUsed()
{
Consumer consumer = container.Resolve<Consumer>();
IFooRepository fooRepository = consumer.fooRepository;
IBarRepository barRepository = consumer.barRepository;
Assert.AreEqual(fooRepository.Database, barRepository.Database); //FAILS
}
[TestMethod]
public void DifferentDatabaseIsUsed()
{
Consumer consumer = container.Resolve<Consumer>();
IFooRepository fooRepository = consumer.fooRepository;
Consumer consumer2 = container.Resolve<Consumer>();
IBarRepository barRepository = consumer2.barRepository;
Assert.AreNotEqual(fooRepository.Database, barRepository.Database); //PASSES
}
[TestInitialize]
public void SetUp()
{
container = new WindsorContainer();
container.Register(
Component.For<Database>().ImplementedBy<Database>().LifeStyle.Transient,
AllTypes.FromThisAssembly()
.BasedOn<IRepository>().WithService.FromInterface()
.Configure(c => c.LifeStyle.Transient),
Component.For<Consumer>().ImplementedBy<Consumer>().LifeStyle.Transient
);
}
}
编辑: 我试图使用自定义的生活方式,但我无法弄清楚我可以用什么来检测我已切换上下文
public class DatabaseLifestyleManager : AbstractLifestyleManager
{
private CreationContext context;
private Database database;
private Database Database
{
get
{
if (database == null) database = new Database();
return database;
}
set
{
database = null;
}
}
public override object Resolve(CreationContext context)
{
if (this.context!=null && this.context.??? == context.???)
return Database;
else
{
this.context = context;
Database = null;
return Database;
}
}
public override void Dispose()
{
database = null;
context = null;
}
}
......
Component.For<Database>().ImplementedBy<Database>().LifeStyle.Custom(typeof(DatabaseLifestyleManager)
答案 0 :(得分:3)
在请求瞬态组件时,您总是会得到一个新实例,如果不是您想要的不使用瞬态生活方式: - )
为什么要注册瞬态组件,但尝试根据某种“上下文”解析同一个对象?很可能这种情况下的生活方式是错误的,而且你很难将其强制转化为不适合的事情。
你想要的是像this article中提到的情境生活方式。 以下两个要点有一个实现:
这将允许您这样做:
Register(Component.For<Database>().LifeStyle.Scoped())
[TestMethod]
public void SameDatabaseIsUsed()
{
using (container.BeginScope())
{
Consumer consumer = container.Resolve<Consumer>();
IFooRepository fooRepository = consumer.fooRepository;
IBarRepository barRepository = consumer.barRepository;
Assert.AreEqual(fooRepository.Database, barRepository.Database); // YAY!
}
}
希望这有帮助!
答案 1 :(得分:2)
答案 2 :(得分:0)
我自己通过实现IDisposable来提出这个解决方案,这样我就可以为数据库使用一种会话镜
这是处理这种情况的有效方法吗?
所有测试通过,但有一些附加功能,必须在我未来的所有存储库使用者中实现:
public class Database { }
public interface IRepository : IDisposable { Database Database { get; } }
public interface IFooRepository : IRepository { }
public interface IBarRepository : IRepository { }
public abstract class BaseRepository : IDisposable
{
public BaseRepository(Database database) { this.Database = database; }
public Database Database { get; private set; }
public void Dispose() { Database = null; }
}
public class FooRepository : BaseRepository, IFooRepository
{
public FooRepository(Database database) : base(database) { }
}
public class BarRepository : BaseRepository, IBarRepository
{
public BarRepository(Database database) : base(database) { }
}
public abstract class BaseConsumer : IDisposable
{
public abstract void Dispose();
}
public class Consumer : BaseConsumer
{
public IFooRepository fooRepository { get; private set; }
public IBarRepository barRepository { get; private set; }
public Consumer(IFooRepository fooRepository, IBarRepository barRepository)
{
this.fooRepository = fooRepository;
this.barRepository = barRepository;
}
public override void Dispose()
{
this.fooRepository.Dispose();
this.barRepository.Dispose();
}
}
[TestClass]
public class ConfigurationTest
{
private IWindsorContainer container;
[TestMethod]
public void SameDatabaseIsUsed()
{
IFooRepository fooRepository;
IBarRepository barRepository;
using (Consumer consumer = container.Resolve<Consumer>())
{
fooRepository = consumer.fooRepository;
barRepository = consumer.barRepository;
Assert.AreEqual(fooRepository.Database, barRepository.Database); //FAILS
}
Assert.IsNull(fooRepository.Database);
Assert.IsNull(barRepository.Database);
}
[TestMethod]
public void DifferentDatabaseIsUsed()
{
IFooRepository fooRepository;
IBarRepository barRepository;
using (Consumer consumer = container.Resolve<Consumer>())
fooRepository = consumer.fooRepository;
Assert.IsNull(fooRepository.Database);
using (Consumer consumer2 = container.Resolve<Consumer>())
barRepository = consumer2.barRepository;
Assert.IsNull(barRepository.Database);
}
[TestInitialize]
public void SetUp()
{
container = new WindsorContainer().Register(
Component.For<Database>().ImplementedBy<Database>().LifeStyle.Singleton,
AllTypes.FromThisAssembly()
.BasedOn<IRepository>().WithService.FromInterface()
.Configure(c => c.LifeStyle.Transient),
Component.For<Consumer>().ImplementedBy<Consumer>().LifeStyle.Transient
);
}
}