代码之家  ›  专栏  ›  技术社区  ›  Tomasz Jaskuλa

DI、构造函数注入、模块、设计模式

  •  3
  • Tomasz Jaskuλa  · 技术社区  · 14 年前

    在我参与的这个项目中,我面临着一些建筑问题。该项目是一个ASP.NET MVC 2应用程序,它依赖于DI,尤其是带有Unity的构造函数注入。应用程序分为几个模块(每个模块是一组组合),向其他模块公开服务。这些服务在应用程序启动时注册到Unity。没有什么特别的,直到现在。假设我有这个(为了简化,每个模块都是一个组件):

    模块A,模块B。

    modulea使用以下方法公开服务“iservicea”:

    iServicea(操作1-操作2-操作3)

    moduleb中的serviceb需要modulea中的iservicea,它是通过构造函数注入(具体实现)获得的。然后它使用它。

    问题是当modulea被取消激活时(如果在应用程序启动时为当前用户激活了该模块,我们将签入数据库),所以servicea没有用Unity注册。

    然后我们在运行时有一个异常,因为Unity找不到IServicea的注册,并且无法构造ServiceB。这是正常的。

    我想知道有一套模式或最佳实践来处理它。不过,我的第一个任务是去掉ServiceB的构造函数注入。但是我应该使用对服务的硬引用,我不喜欢它,或者使用更糟的服务定位器。如果服务A可用或不可用,我不想签入模块B,因为我将签入许多其他服务,并且应该处理纯基础结构的代码。如果服务A可用或不可用(不知道是否可能),我希望该服务B运行相同的代码。我看了一个网关模式,但不知道这是否能帮助我。

    任何帮助都将不胜感激。

    谢谢,

    1 回复  |  直到 14 年前
        1
  •  3
  •   Mark Seemann    14 年前

    你需要一些 默认实现 当模块A停用时,它可以接管。这个 Null Object 图案听起来很合身。

    只需先用Unity注册您的NullServiceA。这将是默认的IServicea,除非被实际实现覆盖(我们称之为ConcreteServiceA)。

    对于更复杂的实现,可以在 Composite 或者其他形式的 Decorator 根据可用性选择其中一个。

    例如,您可以拥有一个始终使用注入到其中的第一个(或最后一个)IServicea实例的组合…或者,选择标准可以基于某种元数据来确定模块是被激活还是被停用(听起来信息本身可以很好地适应假设的IModule接口)。