如何将依赖项注入集成到语言中?[关闭]


10

我一直在思考如何将依赖项注入更好地直接集成到类似C#的语言中。我想出一个潜在的解决方案,希望听听您的意见。我没有使用很多依赖注入框架,所以可能有些东西我忽略了

无论如何,该想法是能够使用关键字将属性声明为“可注入”。当实例化一个对象,并且未通过构造函数或对象初始化程序初始化该属性时,它将从某些全局服务中请求该属性类型的实例。

同样,您可以为该服务注册不同类型的处理程序,以便可以实例化注入的属性类型。

使用这种IMO架构的好处是它相当灵活且易于使用。不利之处在于,每次您启动带有注入的类时,对单身人士进行标注都可能会有一些开销。

再说一次,对于在高性能解决方案中经常实例化的类来说,这只是一个问题,所以这不是什么大问题。在这些情况下,也许您可​​以使用某种工厂。

思想,问题,问题,更好的主意?

public class SomeClass
{

  public SomeClass()
  {
     //implicit behavior if Animal is not set in constructor or initializer
    this.Animal =  GlobalInjector.Get(this,typeof(Mammal))

  }

  public injectable Mammal Animal  
  {
   get;
   set;
  }
}


 GlobalInjector.Register(typeof(Mammal), () => return new Mammal(someParameter));

您能为我们这些不熟悉DI的人提供一个伪代码示例吗?PS。也许您也可以回答有关DI的问题?:)
史蒂文

2
我不确定我明白了。您可以使用全局DI容器和'[Injectable]'属性而不是关键字来获得所有这些信息,对吗?
nikie 2011年

嗨,我曾尝试在您的问题上写一些关于DI的信息,但不确定它是否能回答它
Homde 2011年

nikie:是的,我想您可以通过不同的方式实现实际的机制,如果基础逻辑是合理的,我会更感兴趣
Homde 2011年

那么,除了您的额外关键字之外,此版本与现有的IoC有什么不同?
Matthew Whited

Answers:


7

有些东西属于语言,有些东西不属于语言。很久以前,C意识到IO不属于该语言,因为IO在计算模型的外部并且可以用函数库实现。

依赖注入就是这样。它在语言外部,可以用适当的框架来实现。

现代语言的问题之一是它们尝试做太多事情。最终,由于程序员逃往简单的语言,这些语言在自己的负担下崩溃了。


从理论上我同意,您不能拥有一种语言,其中每个功能都是该语言的功能,而不会使其膨胀。但是,总会有新的更高抽象的空间来帮助我们编写更好的代码。也许依赖注入本身不是需要解决的问题,而是它要解决的问题,即一种使我们更容易减少依赖的方法。但是,这可能不是最好的方法:)
Homde 2011年

5

不用了

我最喜欢使用的最佳DI框架的一件事是,顶级配置代码是代码中唯一需要了解DI的部分。自动装配是在容器和配置/“模块加载”级别完成的,因此您的应用程序代码可以完全忽略它。

这意味着没有属性,没有魔术字符串,没有约定。每一段代码只知道它接受其构造函数(/ properties / methods)中的代码,仅此而已。

使用这样的设计,您根本不需要更改语言即可支持依赖注入。

有潜在危险

对于语言集成的依赖项注入系统,我最担心的事情是它将为任何其他实现带来障碍,但​​在某些方面却可能使自己陷入困境。

它可以将自己绘制到角落的一些方法:

  • 仅支持基于XML的配置,或仅支持基于代码的配置
  • 无法完全支持Factory设计模式(不仅仅是瞬态组件:运行时生成的组件)
  • 以某种方式更改我的代码,因此我被迫使用依赖注入,而不能简单地为单元测试实例化我的类
  • 不支持自定义生命周期
  • 不可扩展
  • 如果我需要更大程度的定制,则无法更换
  • 以某种我们尚不了解的方式被破坏,因为我们的.Net用户使用DI的时间不足以了解陷阱

4

您是否看到过.NET 4随附的托管可扩展性框架?这是我写的一些示例文章。基本上,它是.NET中内置的一种依赖项注入形式,具有运行时发现性的附加功能。

属性注入看起来像这样:

class Program
{
    [Import]
    public IMessageSender MessageSender { get; set; }
}

构造函数注入如下所示:

class Program
{
    [ImportingConstructor]
    public Program(IMessageSender messageSender) 
    {
    ...
    }
}

您可以导入字段,执行可选的导入,导入服务集合,包括使用元数据进行延迟导入,以便可以搜索适当的服务以进行实例化。您甚至可以在运行时重新导入以查找新的扩展名。


尽管MEF对于插件来说真的很酷,但我认为我不希望将其用作一般的DI机制
Homde 2011年

1
@MKO-您能详细说明它缺少什么吗?我知道Glenn Block 竭尽全力向人们保证MEF 不会取代所有DI框架的所有文章,但是如果您查看细节,很明显,这比任何其他内容都更具政治意义。但是,如果您可以列出与其他DI框架相比MEF缺乏的功能,这将有助于人们做出明智的决定。此外,问题在于C#中的DI框架,而MEF显然是.NET框架中的DI容器。
Scott Whitlock

2
  1. 您并没有真正描述配置机制,恕我直言,这很棘手。如何使在一个线程中运行的所有代码都使用DB连接A,而在另一线程连接B中使用所有代码?由于当前登录的用户不允许访问该资源,因此如何阻止注入该资源?
  2. 不要使用全局注射器。根本不要使用任何全局变量,否则您最好也使用全局变量。不,使用单例或“静态”之类的面向对象的语言而不是全局变量不会改变其全局性质。
  3. 考虑一个动态范围的容器。尽管词法作用域理所当然要胜过动态作用域,但我相信动态作用域可以很好地替代全局作用域。差异继承将是一个很好的实现(例如在基于原型的继承中)。
  4. 我认为,语言强制的DI机制应该非常简单,而C#和Java中没有这种企业化的东西。在顶部具有简单配置层的动态范围机制可以解决问题。企业解决方案可以由第三方放在顶层。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.