C# IoC实例共享上下文

C# IoC实例共享上下文,c#,inversion-of-control,castle-windsor,C#,Inversion Of Control,Castle Windsor,我有一个要与存储库共享的datacontext。大多数实现都会重新编译单个容器,因为这样可以节省每次重建整个容器的费用。问题是您需要为每个相关的请求集构建一个完整的新容器及其所有依赖项,例如: class CompanyService : ICompanyService { private IUserRepository _userRepository; private IEmployeeRepository _employeeRepository; public

我有一个要与存储库共享的datacontext。大多数实现都会重新编译单个容器,因为这样可以节省每次重建整个容器的费用。问题是您需要为每个相关的请求集构建一个完整的新容器及其所有依赖项,例如:

 class CompanyService : ICompanyService
{
    private IUserRepository _userRepository;

    private IEmployeeRepository _employeeRepository;

    public CompanyService(IEmployeeRepository employeeRepository,
          IUserRepository userRepository)
    {
        this._employeeRepository = employeeRepository;
        this._userRepository = userRepository;
    }
}
公司服务需要用户和员工存储库,其中每个存储库都需要一个上下文:

class UserRepository : Repository<User>, IUserRepository
{
    public UserRepository(IDataContext dataContext) : base(dataContext) { }
}

class EmployeeRepository : Repository<Employee>, IEmployeeRepository
{
    public EmployeeRepository(IDataContext dataContext) : base(dataContext) { }
}
我希望能够在容器中注册这些类型,如下所示:

    public WindsorContainer BuildContainer()
    {
        var container = new WindsorContainer();
        container.Register(Component.For<SqlContext, IDataContext>());
        container.Register(Component.For<UserRepository, IUserRepository>());
        container.Register(Component.For<EmployeeRepository, IEmployeeRepository>());
        container.Register(Component.For<CompanyService, ICompanyService>());
        return container;
    }
        var container = BuildContainer();
        var service = container.Resolve<ICompanyService>();
然后,我只希望能够按如下方式解决该服务:

    public WindsorContainer BuildContainer()
    {
        var container = new WindsorContainer();
        container.Register(Component.For<SqlContext, IDataContext>());
        container.Register(Component.For<UserRepository, IUserRepository>());
        container.Register(Component.For<EmployeeRepository, IEmployeeRepository>());
        container.Register(Component.For<CompanyService, ICompanyService>());
        return container;
    }
        var container = BuildContainer();
        var service = container.Resolve<ICompanyService>();
我知道默认的实例是singleton,我希望所有这些服务(包括存储库)都是暂时的,但我希望与存储库共享相同的上下文,但只针对特定的请求集

编辑:ThreadLocal或基于请求的实例将不起作用,因为当我从同一个线程解析ICompanyService两次,但在两个上下文中使用时,线程保持不变,IDataContext的实例将保持不变,但它们不应如此

在容器是单例的情况下,我看不到这样做的方法,我看到的唯一方法是使用build函数在每个请求上重建整个容器,并使IDataContext成为单例,其他一切都是暂时的

此方法的另一个问题是,我无法为我打算成为单例的更昂贵的服务重建此容器。不知何故,我需要将容器分成两部分:一部分是包含昂贵服务的主容器,另一部分是我不想重建的主容器,然后是一个派生容器,我可以在我的构建函数中使用它,它将扩展主容器并处理特定于上下文的请求

我只是看错了整个问题,有人能给我指出正确的方向吗


感谢

一种解决方案是提供您自己的UnitOfWork模式,并实现一种定制的生活方式来控制数据上下文的生命周期,而无需将其绑定到线程、web请求等

您必须在UnitOfWork类上使用静态属性才能执行此操作,因此您的工作单元可能如下所示:

public class UnitOfWork : IDisposable {
    [ThreadStatic]
    public static UnitOfWork Current { get; set; }

    private IDictionary<string, object> _items;

    public IDictionary<string, object> Items 
    {
         get { 
              if(_items == null) 
              {
                 _items = new Dictionary<string, object>();
              }
              return _items;
         }
    }

    public void Dispose()
    {
         Current = null;
    }

    public static UnitOfWork Start() 
    {
         Current = new UnitOfWork();
         return Current;
    }
}
using(UnitOfWork.Start())
{
    var companyService = container.Resolve<ICompanyService>();
    // .. use company service
}
public class UnitOfWorkLifestyleManager : AbstractLifestyleManager
{
    private string PerUnitOfWorkObjectID = "UnitOfWorkLifestyleManager_" + Guid.NewGuid().ToString(); 

    public override object Resolve()
    {
        if(UnitOfWork.Current.Items[PerUnitOfWorkObjectID] == null)
        {
            // Create the actual object
            UnitOfWork.Current.Items[PerUnitOfWorkObjectID] = base.Resolve();  
        }

        return UnitOfWork.Current.Items[PerUnitOfWorkObjectID];
    }

    public override void Dispose()
    { 
    }
}
并注册您的定制生活方式:

container.Register(Component.For<SqlContext, IDataContext>().Lifestyle.Custom<UnitOfWorkLifestyle>());

不要解决ICompanyService两次-你不需要这样做,如果你不这样做,你的问题就解决了。相反,请使用RRR模式:Hi Mark,问题不在于服务,而在于用户和员工存储库,他们需要获得相同的IDataContextYes实例,但是如果我假设每个HTTP请求只解决一次,那么PerWebRequest的生存期应该足够了……Hi Mark,谢谢你的回答,但这里有一点我理解不正确:在我的示例中,我有一个服务,依赖于两个存储库,取决于一个上下文。这些对象中的每一个都必须是唯一的实例,但上下文除外,上下文只解析一次并在存储库之间共享。但仅限于每项服务。当对容器进行调用时。解析如果每个请求有一个调用图,这将很好,因为随后将共享单个上下文。但是如果有两个服务这样调用:container,该怎么办?解析将具有相同的上下文,这是正确的,但另一个对:container的调用。解析将与服务1共享相同的上下文,这是正确的错误这两个服务在同一线程中解决