具有静态和动态依赖关系的IoC

我试图在我的应用程序中实现IoC。 我有这个模型:

interface IService;
interface IComponent;

class Service : IService
    Service()

class Component : IComponent
    Component(IService service, object runtimeValue) { }

在我的应用程序的某个时刻,我需要获得一个IComponent 。 我的应用程序使用IoC容器(Unity)。 我可以在容器中注册Service ,但是我不能对它的dependency runtimeValue Component b / c做同样的事情。 根据这一点,我必须使用工厂,并在需要获取IComponent地方注入:

interface IComponentFactory
     IComponent CreateComponent(object runtimeValue)

class ComponentProvider : IComponentProvider
     ComponentProvider(IComponentFactory factory) { }

     IComponent CreateAndCacheComponent(object runtimeValue) {
         _component = factory.CreateComponent(runtimeValue)
         return _component
     }

     // other methods

我必须能够在容器中注册工厂,所以它必须只有静态依赖。 同时它必须能够提供创建组件所需的IService类型的服务实例。
这是工厂实施。 我唯一能想到的就是使用Func<>委托作为依赖关系:

class ComponentFactory : IComponentFactory
    ComponentFactory(Func<IService> serviceFactoryDelegate)

    IComponent CreateComponent(object runtimeValue) {
        return new Component(serviceFactoryDelegate.Invoke(), runtimeValue)
    }

...并将容器的委托注册为静态工厂,以便它回调容器以解析服务(我在.net 2.0上使用Unity 1.2):

Container
    .Configure<IStaticFactoryConfiguration>()
    .RegisterFactory<Func<IService>>(container => (Func<IService>)container.Resolve<IService>)

现在我可以使用容器来解析ComponentProvider并根据运行时值获取组件:

// this happens inside CompositionRoot
provider = Container.Resovle<IComponentProvider>()
component = provider.CreateAndCacheComponent("the component")

现在我对此有一些疑问:

  • 我不高兴工厂调用new Component(...) 。 这个可怜的人是不是DI?

  • 在工厂的构造函数中使用Func<IService>时,好莱坞原理是否仍然存在? 我的意思是,它最终调用container.Resolve <> ...有点像SL。 唯一的区别是代码是在应用程序的容器注册部分,而不是在工厂类中。

  • 就DI和IoC而言,这个实现有什么(其他)错误吗?


  • 这离贫穷人的DI很远,但是如果每当新的依赖项被添加到组件的构造函数中时不需要改变这个工厂方法,那将会很好。
  • 这本身不是问题。 把它想像成你正在注入一个匿名的工厂类。 它仍然可以被模拟进行单元测试,并且绑定可以被改变,所以你仍然可以获得DI的好处。 但它是一个附加的抽象层,可能不是必需的。 在这种情况下,您仍然可以通过将IService直接注入工厂而不是Func来避免它。
  • 通常在使用依赖注入时,您想要注入服务而不是值。 事实上,你发现你必须同时拥有这两个可能表明你需要重新考虑你的班级的API。 例如,也许你应该将值传递给类中的方法而不是构造函数。 不知道更多细节,很难说最好的方法是什么。

  • 不,它不是。 工厂的全部目的是创建一个具体类的实例。
  • 基本上,是的,但正如我在评论中已经提出的那样,我不明白为什么这是必要的。 你可以直接注入一个IService实例
  • 这比它需要更复杂一点。 为什么双重定向IComponentProvider - > IComponentFactory ? 它看起来像IComponentFactory不会增加任何好处。

    像这样实现ComponentProvider

    class ComponentProvider : IComponentProvider
    {
        ComponentProvider(IService service) { _service = service; }
    
        IComponent CreateAndCacheComponent(object runtimeValue) {
            _component = new Component(_service, runtimeValue);
            return _component;
    }
    

    这会给你以下好处:

  • 您将删除不必要的接口IComponentFactory以及相应的实现。
  • 无需为IService注册工厂

  • 一般来说,你如何实现这取决于你真正需要什么:

    “runtimeValue”在整个运行时可以相同,例如从设置中读取的连接字符串。 在这种情况下,不需要工厂/提供者,您可以简单地新建实例并将其注册到容器中。 每个需要IComponent人在构造函数中请求一个而不是提供者。

    如果“runtimeValue”在对CreateAndCacheComponent调用之间真正发生更改,您只会实现一个工厂并将它作为依赖项CreateAndCacheComponent


    对于问题1:在工厂中调用new没有任何问题。 你在你的应用程序中有一个独立的实例化; 你只是让这个工厂代替了容器。

    如果您需要模拟或更改实现,则只需模拟或更改工厂实现,而不是单独使用组件。

    链接地址: http://www.djcxy.com/p/65663.html

    上一篇: IoC with static and dynamic dependencies

    下一篇: Not understanding where to create IoC Containers in system architecture