Dependency injection 如何在与Castle Windsor DI容器相同的上下文中重用临时依赖项

Dependency injection 如何在与Castle Windsor DI容器相同的上下文中重用临时依赖项,dependency-injection,castle-windsor,ioc-container,Dependency Injection,Castle Windsor,Ioc Container,如果我有以下设置,当在相同的上下文中创建对象时,如何配置容器以使用相同的数据库 public class Database { } public interface IRepository { Database Database { get; } } public interface IFooRepository : IRepository { } public interface IBarRepository : IRepository { } public class FooReposit

如果我有以下设置,当在相同的上下文中创建对象时,如何配置容器以使用相同的数据库

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
                    );

    }
}
公共类数据库{}
公共接口IRepository{Database Database{get;}}
公共接口IFooRepository:IRepository{}
公共接口IBarRepository:IRepository{}
公共类FooRepository:IFooRepository
{
公共数据库{get;private set;}
公共FooRepository(数据库){this.Database=Database;}
}
公共类BarRepository:IBarRepository
{
公共数据库{get;private set;}
公共存储库(数据库){this.Database=Database;}
}
公共类消费者
{
公共IFooRepository fooRepository{get;private set;}
公共IBarRepository barRepository{get;私有集;}
公共消费者(IFooRepository、IBarRepository)
{
this.fooRepository=fooRepository;
this.barRepository=barRepository;
}
}
[测试类]
公共类配置测试
{
私人集装箱;
[测试方法]
public void SameDatabaseIsUsed()
{
Consumer=container.Resolve();
IFooRepository foosrepository=consumer.foosrepository;
IBarRepository barRepository=消费者。barRepository;
Assert.AreEqual(fooRepository.Database,barRepository.Database);//失败
}
[测试方法]
public void differentitdatabaseisused()
{
Consumer=container.Resolve();
IFooRepository foosrepository=consumer.foosrepository;
Consumer consumer2=container.Resolve();
IBarRepository barRepository=消费者2.barRepository;
Assert.AreNotEqual(fooRepository.Database,barRepository.Database);//通过
}
[测试初始化]
公共作废设置()
{
容器=新WindsorContainer();
集装箱。登记(
Component.For().ImplementedBy().LifeStyle.Transient,
AllTypes.FromThisAssembly()
.BasedOn().WithService.FromInterface()
.Configure(c=>c.lifesture.Transient),
Component.For().ImplementedBy().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)
公共类数据库LifeStyleManager:AbstractLifestyleManager
{
私人创作语境;
专用数据库;
专用数据库
{
得到
{
如果(database==null)database=newdatabase();
返回数据库;
}
设置
{
数据库=null;
}
}
公共重写对象解析(CreationContext上下文)
{
if(this.context!=null&&this.context.??==context.??)
返回数据库;
其他的
{
this.context=上下文;
数据库=null;
返回数据库;
}
}
公共覆盖无效处置()
{
数据库=null;
上下文=空;
}
}
......
Component.For().ImplementedBy().LifeStyle.Custom(typeof(DatabaseLifestyleManager)

我自己通过实现IDisposable提出了这个解决方案,这样我就可以为数据库使用一种sessionscope

这是处理这种情况的有效方法吗

所有测试都通过,但还有一些附加功能,必须在存储库的所有未来使用者中实现:

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
                    );
    }
}
公共类数据库{}
公共接口IRepository:IDisposable{Database Database{get;}}
公共接口IFooRepository:IRepository{}
公共接口IBarRepository:IRepository{}
公共抽象类BaseRepository:IDisposable
{
公共BaseRepository(数据库){this.Database=Database;}
公共数据库{get;private set;}
public void Dispose(){Database=null;}
}
公共类FooRepository:BaseRepository、IFooRepository
{
公共FooRepository(数据库):base(数据库){}
}
公共类存储库:BaseRepository、IBarRepository
{
公共存储库(数据库):基(数据库){}
}
公共抽象类BaseConsumer:IDisposable
{
公开摘要无效处置();
}
公共类消费者:BaseConsumer
{
公共IFooRepository fooRepository{get;private set;}
公共IBarRepository barRepository{get;私有集;}
公共消费者(IFooRepository、IBarRepository)
{
this.fooRepository=fooRepository;
this.barRepository=barRepository;
}
公共覆盖无效处置()
{
这个.foodrepository.Dispose();
this.barRepository.Dispose();
}
}
[测试类]
公共类配置测试
{
私人集装箱;
[测试方法]
public void SameDatabaseIsUsed()
{
IFooRepository-fooRepository;
iBarrespositive Barrespositive;
使用(Consumer=container.Resolve())
{
fooRepository=consumer.fooRepository;
barRepository=消费者。barRepository;
Assert.AreEqual(fooRepository.Database,barRepository.Database);//失败
}
Assert.IsNull(fooRepository.Database);
IsNull(barRepository.Database);
}
[测试方法]
public void differentitdatabaseisused()
{
IFooRepository-fooRepository;
iBarrespositive Barrespositive;
使用(Consumer=container.Resolve())
fooRepository=consumer.fooRepository;
Assert.IsNull(fooRepository.Database);
使用(Consumer-consumer2=container.Resolve())
barRepository=消费者2.barRepository;
IsNull(barRepository.Database);
}
[测试初始化]
公共作废设置()
{
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!
    }
}