依赖注入和库/框架 [英] Dependency injection and Libraries/Frameworks

查看:194
本文介绍了依赖注入和库/框架的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,也许这里有这样的问题了,但我没有发现它。

OK, maybe here is such question already, but I didn't find it..

我们有很多的入口点大的企业应用程序。应用包含这样的部分:

We have big enterprise application with a lot of entry points. App contains part like:


  • 服务器

  • 桌面客户端

  • 一些控制台应用

  • .NET API(单独的程序,一个名为如 MyAppAPI 根类)

  • COM API(同样,单独的程序,你可以从访问API,例如VBScript中,由一套API =的CreateObject(MyApp.MyAppAPI)

  • 的Java API(再次,下同)

  • 消息API(单独的程序,用于通过消息队列层之间的通信)

  • Server
  • Desktop Client
  • Some console utilities
  • .NET API (separate assembly, with root class called like MyAppAPI)
  • COM API (the same, separate assembly, you can access to API from, for example VBScript, by Set api = CreateObject("MyApp.MyAppAPI")
  • Java API (again, the same)
  • Messaging API (separate assembly, used for communicating between layers through messages queues)

我们使用统一为在此应用程序的DI容器一切都在服务器酷/ DesktopClient /控制台工具等等 - 有非常具体的切入点,所以我们只初始化成分根一个对象,初始化对象/依存关系,一切的树就像一个魅力,他们的问题是与我们的API。

We use Unity as DI container in this app. Everything is cool in Server/DesktopClient/Console utilities etc. - there are very concrete entry points, so we just initialize composition root object there, initialize tree of objects/dependencies, and everything works like a charm. Them problem is with our APIs.

如何应对DI在库/框架

How to deal with DI in libraries/frameworks?

从上面的链接:

的组成Root是应用程序基础设施组件。

The Composition Root is an application infrastructure component.

只有应用应该构成根。库和
框架不应该。

Only applications should have Composition Roots. Libraries and frameworks shouldn’t.

是的,这很酷,但..我想在我的API使用DI , 它超大!如何处理一个用其他的?

Yeah, it's cool, but.. I want to use DI in my API, it's huge! How to deal one with other?

我们有依赖,它最好应该是单身(如一些工厂,它控制创建对象的生命周期)。但是,我们可以创建API对象的某些情况下,如何分享他们之间的这种单实例?甚至更多 - 我们可以创建.NET API对象,并在同一个域中COM API的一个对象/某些情况下的某些情况下(如果你愿意,我可以在注释中解释,当它的可能)。

We have dependencies, which preferably should be singletons (e.g. some factories, which control lifetime of created objects). But, we can create some instances of API objects, how to share this singleton instances between them? Even more - we can create some instances of .NET API objects and one/some instances of COM API objects in the same domain (if you want, I can explain in the comment when it's possible)..

正如我所说的,没有与应用程序没有问题,在图书馆(API)的存在问题。所以,我现在有

As I said, there is no problem with apps, the problem exists in libraries (APIs). So, what I have now


  • 我有类 ShellBase

  • 这个类包含静态字段 _Shells 与公共静态方法获取发布

  • 有容器之间的层次结构(如API的'容器由MessagingAPI,服务器和DesktopClient容器由.NET API容器等继承继承。)

  • 当有人问新的外壳(通过获取法), ShellBase 检查已经有这样的容器(或超容器,从子类),并返回该实例。或者创建新的

  • I have class ShellBase
  • this class contains static field _Shells and public static methods Get and Release
  • there is hierarchy between containers (e.g. APIs' containers are inherited from MessagingAPI, Server and DesktopClient containers are inherited from .NET API container etc.)
  • when somebody ask for new shell (through Get method), ShellBase checks if there is already such container (or super-container, from subclass), and returns that instance. Or creates new one

我不喜欢这样,但是这是最好的我现在能想象的。

I don't like this way, but this is the best what I can imagine right now.

创建类似 APIFactory ,这将创造我们的API对象,但它看起来..对终端用户过于复杂。我不希望用户文档中这样写:请,创建并先留着APIFactory实例,那么您可以创建使用此工厂API实例。它很丑。我们的用户应该仅编写 VAR API =新的API(),并使用它。

Create something like APIFactory, which will create our API objects, but it looks.. too complicated for end-users. I don't want to write in user documentation: "Please, create and keep APIFactory instance first, then you can create API instances using this factory". It's ugly. Our users should write just var api = new API(), and use it.

所以,伙计们,什么?你觉得

So, guys, what do you think?

推荐答案

1 我看到其他框架/他们介绍自己的图书馆DI容器抽象,经由接口。然后,他们使用这个接口在内部无论他们需要引用DI容器。适配器用于他们的图书馆与特定的DI容器连接。例如,戴维·布里翁的阿加莎项目有以下容器接口: https://github.com/davybrion/Agatha/blob/master/Agatha.Common/InversionOfControl/IContainer.cs 他为最常用的DI容器提供的适配器。

1: I have seen other frameworks/libraries where they introduce their own DI container abstraction, via an interface. They then use this interface internally wherever they need to reference the DI container. Adapters are used to connect their library with a specific DI container. For example, Davy Brion's Agatha project has the following Container interface: https://github.com/davybrion/Agatha/blob/master/Agatha.Common/InversionOfControl/IContainer.cs and he supplies adapters for the most used DI containers.

2 我不是完全肯定我这里理解你的问题,但大多数,如果不是全部,DI容器支持单身一辈子的范围,这意味着你的容器将只创建一个实例。例如,在ninject你会做:

2: Im not entirely sure I understand your problem here, but most, if not all, DI containers support singleton lifetime scopes, meaning your container will only ever create a single instance. For example, in ninject you would do:

kernel.Bind<IFoo>()
   .To<Foo>()
   .InSingletonScope();



另外,如果你想避免公共构造,可以使类像的静态单一实例你会做没有DI容器。您可以用一个返回实例的工厂方法的容器注册您的单一实例。同样,ninject例如:

Alternatively, if you want to avoid public constructors, you can make a static singleton instance of the class like you would do without a DI container. You can the register your singleton instance with the container with a factory method that returns that instance. Again, a ninject example:

kernel.Bind<IFoo>()
    .ToMethod(c => Foo.Instance);



由于接口上面介绍的,你应该能够分享您的API之间的一个容器实例(假设您在给定的应用多个API),从而强制执行单的要求。

Given the interface introduced above, you should be able to share a single container instance between your APIs (assuming you use more than one API in a given application), thereby enforcing the singleton requirement.

如果这不是你的问题,那么也许你可以在第二个问题阐述。

If this is not your problem, then maybe you can elaborate on the second problem.

这篇关于依赖注入和库/框架的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆