IoC Instancing困境共享上下文

时间:2011-11-02 08:18:44

标签: c# inversion-of-control castle-windsor

我有一个我想与存储库共享的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>();

我知道默认实例化是单例,我希望包括存储库在内的所有这些服务都是暂时的,但我想与存储库共享相同的上下文但仅针对特定的请求集。

编辑:ThreadLocal或基于请求的实例将无法工作,因为当我从同一个线程解析ICompanyService两次但在2个上下文中使用时,线程保持不变,而IDataContext的实例将是相同的,但它们不应该是。< / p>

我没有看到这样做容器是单例的方法,我看到的唯一方法是使用构建函数在每个请求上重建整个容器,并使IDataContext成为单例,其他一切都是瞬态的。

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

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

由于

1 个答案:

答案 0 :(得分:0)

一种解决方案是提供您自己的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>());