c# - 移除对 IoC 容器的依赖

标签 c# dependency-injection inversion-of-control ioc-container

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

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

我想编写如下代码:

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

但是我怎样才能摆脱 IoC.Resolve 调用呢?也许我需要更好地了解 DI...

提前致谢。

最佳答案

一般来说,大多数依赖项都可以在创建类时注入(inject)到你的类中。但是,在这种特殊情况下,您需要一个必须在使用时按需创建的组件。在这种情况下,很难完全消除对 IoC 容器的依赖。我的方法一直是创建一个在创建时注入(inject)到类中的工厂,它又封装了所有直接的 IoC 使用。这允许您的工厂被模拟进行测试,而不是 IoC 容器本身......这往往要容易得多:

// 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 框架注入(inject)到它们的依赖项中。例如,如果您正在使用 CaSTLe Windsor,您将创建配置,告诉 IoC 容器在创建时将这两个工厂注入(inject)到您的业务组件中。业务组件本身也可能有一个工厂……或者,它可能只是被同一个 IoC 框架注入(inject)到更高级别的组件中,等等,等等。

关于c# - 移除对 IoC 容器的依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3154075/

相关文章:

c# - mysql外部访问

c++ - 依赖注入(inject)库的正确比喻是什么?

java - 理解Spring注解DI

domain-driven-design - DDD 聚合和实体中的 InversionOfControl(依赖注入(inject))

compact-framework - 当具体类型派生自抽象基类时,Ninject 无法解析接口(interface)类型

c# - 瓦廷评估问题

c# - 无法自动进入服务器。调试器未能在服务器进程中停止

C# - 将泛型接口(interface)转换为传递在运行时确定的类型 <T> 的泛型类

dependency-injection - ASP.NET MVC 3 RC 中的 MvcServiceLocator 在哪里?

nhibernate - 如何停止 Fluently.Configure 自动连接