【问题标题】:Dependency Injection Initialization依赖注入初始化
【发布时间】:2013-12-30 06:46:42
【问题描述】:

请注意:我刚刚开始使用 AutoFac 来了解 DI 和 IoC。

依赖注入是否应该在控制器构造函数中初始化?

这是怎么回事?

private IMyService iMyService;
public HomeController(IMyServices myService)
{
    iMyService = myService;
}

不同于...

public IMyService iMyService = new MyService();

最后,依赖似乎仍然存在。

编辑:修正错字,new MyService();是新的 IMyService();

【问题讨论】:

    标签: c# asp.net-mvc dependency-injection inversion-of-control


    【解决方案1】:

    Dependency Injection 表示完全依赖注入。它没有说明初始化。例如。如果你注入的是单例的依赖,那么它可以在你注入它之前很久就被初始化。

    您的第一个代码是通常的dependency injection via constructor。您的第二个代码不是依赖注入。实际上这对我来说看起来很奇怪——要么你试图创建接口实例,这是不可能的,要么你在这里命名不好。如果只是错误的命名或拼写错误,那么第二个示例应该看起来像:

     public IMyService iMyService = new MyServiceImplementation();
    

    但是你没有在这里注入任何东西。您只是在创建依赖实例(这使您的控制器与依赖实现耦合)。

    【讨论】:

      【解决方案2】:

      编辑,依赖总是“存在”,但它被移到了类之外 请注意,IMyServices 现在可以在与HomeController 相同的项目中定义 当MyService 完全属于另一个班级时。并且您的带有 HomeController 的 DLL 可以在不知道您的 MyService dll 的情况下有效地解耦它们。


      这是一个非常复杂的话题,您应该阅读有关它的书。阅读博客视频等并没有真正的帮助。

      这是一本好书。 http://www.amazon.com/Dependency-Injection-NET-Mark-Seemann/dp/1935182501

      这是一个很棒的视频讲座系列,前 5 个视频是关于 DI 的 http://channel9.msdn.com/Blogs/mtaulty/Prism--Silverlight-Part-1-Taking-Sketched-Code-Towards-Unity

      初始化集中在COMPOSITION ROOT http://blog.ploeh.dk/2011/07/28/CompositionRoot/

      您在此处显示的模式是 CONSTRUCTOR INJECTION

      https://softwareengineering.stackexchange.com/questions/177649/what-is-constructor-injection

      【讨论】:

      • 感谢推荐书。
      【解决方案3】:

      依赖注入并非微不足道——这个概念很简单,但理解它可能需要一些实践和研究。让我举一个使用DI的地方的例子,也许它会有意义(可能不是最好的例子,抱歉我想不出更好的ATM):

      假设你有以下课程:

      public class MyAwesomeClass {
         private readonly IConfig _config;
      
         public MyAwesomeClass(IConfig config) {
            _config = config;
         }
      
         public IEnumerable<string> GetFiltered() {
            IEnumerable<string> results = _config.GetSettings();
      
            // filter my results
            return results.Where(x => x.StartsWith("awesome", StringComparison.OrdinalIgnoreCase));
         }
      }
      

      现在,如果您要测试 GetFiltered,您可以注入 IConfig 的虚假实现,并确保您的过滤器正常工作(您将您的代码与依赖项隔离)。您还反转控件,通过公开依赖项并让您的类的用户来处理它们,您几乎是在说 - “如果你想让我工作,我需要你给我一个IConfig 的实现,你来处理。”

      这是测试的样子

      [Test]
      public void GetsOnlyResultsContainingAwesome() {
         var fakeConfig = new FakeConfig();
         var awesome = new MyAwesomeClass(fakeConfig);
      
         IEnumerable<string> results = awesome.GetFiltered();
      
         Assert.AreEqual(2, results.Count());        
      }
      

      这是IConfig的假实现

      public class FakeConfig : IConfig {
         public IEnumerable<string> GetSettings() {
            return new List<string> { "test1", "test2", "awesome1", "awesome2" };
         }
      }
      

      我希望这是有道理的。对不起,如果我的例子不好,但我只是想说明一点。

      【讨论】:

      • 我只是迟到了两年,但是...谢谢。我仍然一直使用它进行测试。
      【解决方案4】:

      你可以这么说。实际上 AutoFac、ninject 等具有将接口与类绑定的功能。所以你需要先这样做。我的意思是说你需要创建一个类,你需要让 AutoFac 和 ninject 将它与接口绑定。

      因此,当控制器将寻找任何特定的接口时,AutoFac 和 ninject 只会创建该类的对象并将其分配给接口。就初始化而言,您可以在将类与接口绑定时初始化值。

      【讨论】:

        【解决方案5】:
        private IMyService iMyService;
        public HomeController(IMyServices myService)
        {
            iMyService = myService;
        }  
        

        在这种情况下,你只关心你需要什么(IMyServices)

        public IMyService iMyService = new MyService();  
        

        但在这种情况下,你关心的是它会是什么(new MyService())

        在设计课程时,您知道自己需要什么;
        但它会是什么,这不是由你决定的,由谁使用你的课程来决定

        【讨论】:

          猜你喜欢
          • 2013-07-27
          • 1970-01-01
          • 2021-05-15
          • 1970-01-01
          • 1970-01-01
          • 2011-04-19
          • 2013-07-08
          • 1970-01-01
          • 2018-01-15
          相关资源
          最近更新 更多