代码之家  ›  专栏  ›  技术社区  ›  TheCloudlessSky

删除对IoC容器的依赖关系

  •  17
  • TheCloudlessSky  · 技术社区  · 14 年前

    在读了越来越多关于IoC容器的内容之后,我读到 this post 关于代码中没有IoC.Resolve()等。

    我真的很想知道,怎样才能消除对容器的依赖?

    我想编写如下代码:

    public void Action()
    {
        using(IDataContext dc = IoC.Resolve<IDataContext>())
        {
            IUserRepository repo = IoC.Resolve<IUserRepository>();
            // Do stuff with repo...
        }
    }
    

    但我怎样才能摆脱国际奥委会。解决问题?也许我需要更好的了解我的。。。

    提前谢谢。

    5 回复  |  直到 7 年前
        1
  •  17
  •   jrista    14 年前

    // In Presentation.csproj
    class PresentationController
    {
        public PresentationController(IDataContextFactory dataContextFactory, IRepositoryFactory repositoryFactory)
        {
            #region .NET 4 Contract
            Contract.Requires(dataContextFactory != null);
            Contract.Requires(repositoryFactory != null);
            #endregion
    
            _dataContextFactory = dataContextFactory;
            _repositoryFactory = repositoryFactory;
        }
    
        private readonly IDataContextFactory _dataContextFactory;
        private readonly IRepositoryFactory _repositoryFactory;
    
        public void Action()
        {
            using (IDataContext dc = _dataContextFactory.CreateInstance())
            {
                var repo = _repositoryFactory.CreateUserRepository();
                // do stuff with repo...
            }
        }
    }
    
    // In Factories.API.csproj
    interface IDataContextFactory
    {
        IDataContext CreateInstance();
    }
    
    interface IRepositoryFactory
    {
        IUserRepository CreateUserRepository();
        IAddressRepository CreateAddressRepository();
        // etc.
    }
    
    // In Factories.Impl.csproj
    class DataContextFactory: IDataContextFactory
    {
        public IDataContext CreateInstance()
        {
            var context = IoC.Resolve<IDataContext>();
            // Do any common setup or initialization that may be required on 'context'
            return context;
        }
    }
    
    class RepositoryFactory: IRepositoryFactory
    {
        public IUserRepository CreateUserRepository()
        {
            var repo = IoC.Resolve<IUserRepository>();
            // Do any common setup or initialization that may be required on 'repo'
            return repo;
        }
    
        public IAddressRepository CreateAddressRepository()
        {
            var repo = IoC.Resolve<IAddressRepository>();
            // Do any common setup or initialization that may be required on 'repo'
            return repo;
        }
    
        // etc.
    }
    

    这种方法的好处是,虽然不能完全消除IoC依赖本身,但可以将其封装在单一类型的对象(工厂)中,从而将大部分代码与IoC容器分离。这提高了代码的灵活性,例如,从一个IoC容器切换到另一个(即从Windsor到Ninject)。

    值得注意的是,这样做的一个有趣的结果是,您的工厂通常被注入到它们的依赖项中,使用的是相同的IoC框架。例如,如果您使用的是castlewindsor,那么您将创建一个配置,告诉IoC容器在创建业务组件时将这两个工厂注入到业务组件中。业务组件本身也可能有一个工厂……或者,它可能只是被同一个IoC框架注入到一个更高级别的组件中,等等,adinf。

        2
  •  3
  •   TheCloudlessSky    13 年前

    Func<T>

    public void Action(Func<IDataContext> getDataContext, Func<IUserRepository> getUserRepository)
    {
        using(IDataContext dc = getDataContext())
        {
            IUserRepository repo = getUserRepository();
            // Do stuff with repo...
        }
    }
    
        3
  •  2
  •   mschaef    14 年前

    前段时间我在做一个项目,还没有确定一个IoC容器。他们通过禁止非IoC特定的容器特性和包装来管理不确定性 Resolve

    这是一种可行的技术,但在某个时候,你必须选择你使用的工具,并愿意接受你将支付费用,以切换到其他工具。对我来说,IoC容器属于你可能应该全心全意接受的范畴,所以我对这一级别的分解提出质疑。如果您想进一步了解这一点,我建议使用以下链接:

    http://blog.objectmentor.com/articles/2010/01/17/dependency-injection-inversion

        4
  •  2
  •   o3o Krzysztof Kozmic    12 年前

    我最近在博客上提到了这个问题:

        5
  •  1
  •   trejder tvCa    10 年前

    让第二个依赖注入程序注入第一个依赖注入程序,让第一个依赖注入程序注入第二个依赖注入程序。