5

所以控制反转是一个模糊的描述,所以依赖注入成为了新的定义。这是一个非常非常强大的解决方案,很可能对从未遇到过它的人感到困惑。

因此,为了不成为头灯中的鹿,我阅读了。我发现了几本很棒的书和在线帖子。但就像所有美妙的事情一样,更多的问题出现了,而不是答案。

问题是从未知项目中吸收变量,一旦它们被引入我的项目中就可以实施。

解决方案:

public interface ISiteParameter
{
    Guid CustomerId { get; set; }
    string FirstName { get; set; }
    string LastName { get; set; }
    string Phone { get; set; }
}

我的注射器:

public interface IInjectSiteParameter
{
     void InjectSite(ISiteParameter dependant);
}

然后我创建了这个:

public class SiteContent : IInjectSiteParameter
{
    private ISiteParameter _dependent;

    #region Interface Member:
    public void InjectSite(ISiteParameter dependant)
    {
        _dependant = dependant;
    }
    #endregion
}

然后使用共享引用来实现它作为 Fed 变量,我创建了一个要实现的类,例如:

public class SiteParameters : ISiteParameter
{    
   public Guid Customer Id { get; set; }
   public string FirstName { get; set; }
   public string LastName  { get; set; }
   public string Phone { get; set; }
}

现在SiteParameters Class将被另一个项目引用;这将允许我随时随地通过以下方式实际调用这些属性:

ISiteParameter i = new ISiteParameter();
MessageBox.Show(i.Guid + i.FirstName + i.LastName + i.Phone);

那是实现,但我的问题是……我什么时候使用?

  • 构造函数注入
  • 二传手注入
  • 接口注入

您什么时候使用其中一种?对于我提到的任务,我是否应该实施如此艰巨的任务来调整对其他项目所做的任何更改?

我是否在思考过程中偏离了曲线?

4

2 回答 2

3

摘自Mark Seemann的 .NET 中的依赖注入的第 4 章

构造函数注入应该是 DI 的默认选择。它解决了一个类需要一个或多个依赖项的最常见场景。如果依赖的类在没有依赖的情况下绝对不能运行,那么保证是有价值的。

仅当您正在开发的类具有良好的本地默认值并且您仍希望使调用者能够提供类依赖项的不同实现时,才应使用属性注入。属性注入也可用于框架要求您具有默认构造函数的情况,例如 ASP.NET 页面。

当依赖项可能随每个方法调用而变化时,最好使用方法注入。当依赖项本身表示一个值时,可能会出现这种情况,但当调用者希望向消费者提供有关调用操作的上下文的信息时,通常会出现这种情况。

于 2013-03-07T00:32:30.933 回答
1

在可能的情况下,我使用构造函数来传递依赖关系,而不是通过方法调用进行注入。

例如:

public interface IWebHost 
{ 
   string DoSomething(string input); 
} 

public class FooManager 
{
   private IWebHost _host; 
   public FooManager(IWebHost host)
   {  
      _host = host; 
   } 

   public void Process()
   { 
      // do something with _host 
   }
} 

这样做有很多好处,但我认为最有益的有两个:

  • 我的依赖项是预先指定的,错过的可能性较小。
  • 我可以使用依赖注入存储库自动为我进行构建。

在某些情况下,这样做是不可能或不切实际的,但大多数情况都可以通过注入为我进行构造的工厂来解决。

另一个例子:

public interface IConnection : IDisposable 
{
   string DoSomething(string input); 
   // implement IDisposable
}

public interface IConnectionFactory 
{
   IConnection CreateConnection(); 
} 

public class DerpConnection : IConnection 
{
    // implementation
} 

public class DerpConnectionFactory : IConnectionFactory 
{
  // We only return DerpConnections from this factory.  

  IConnection CreateConnection() { return new DerpConnection(); } 
}

public class BarManager 
{ 
   private IConnectionFactory _connectionFactory; 
   public BarManager(IConnectionFactory connectionFactory)
   {   
      _connectionFactory = connectionFactory;
   } 

   public void Manage()
   {
      using(var connection = _connectionFactory.CreateConnection()) 
      { 
        // do something here. 
      } 
   }
}

DI框架只需要知道IConnectionFactory这个例子中的,Factory实现直接构造DerpConnection. 在单元测试中,我可以轻松地模拟工厂和 IConnection 响应。

不可能的场景,通常表明某种横切关注点,或者该类比它需要的复杂得多(并且违反了SRP

于 2013-03-07T00:41:09.130 回答