构造具有函数作为依赖注入手段的对象

时间:2011-02-07 19:07:57

标签: c# function dependency-injection

我偶然发现了一些代码,我很好奇为什么会这样。

有两个构造函数,主要一个在代码中调用,第二个用于测试依赖注入。第二个构造函数接受了一个函数,该函数返回对象而不是对象本身的实例。

MainConstructor()  
:this(() => Factory.Current.GetInstance<IQueryService>()){ 
}

SecondConstructor(Func<IQueryService> getQueryService){
}

我很好奇你传递函数而不是实例所带来的好处。

3 个答案:

答案 0 :(得分:1)

做这样的事情有几个可能的好处:

  1. 解耦:通过允许调用者传入委托而不是实例,调用者和被调用者(在您的情况下是正在构造的类)都可以与传递的对象分离。来自哪里。
  2. 延迟获取:通过传入委托,可以以懒惰的方式获取实例。换句话说,构造函数原则上可以缓存委托并在最后可能的时刻调用它,仅在实际需要实例时才调用它。如果永远不需要该实例,则可能永远不会创建该实例。
  3. 可重新安全性:通过传入委托而不是实例,该类可以缓存用于按需创建查询服务的机制。通过这种方式,委托充当工厂,允许按需创建所需类型的实例。

答案 1 :(得分:0)

使用Func<T>允许延迟创建产品,这对于可选的依赖项非常有用 - 例如,其中一个类方法可能如下所示:

public void SomeMethod()
{
    if(someCondition)
    {
        IQueryService service = this.getQueryService();
        service.Execute():
    }
}

如果IQueryService创建成本高,如果someCondition永远不会评估为真,则可以提高效率。

答案 2 :(得分:0)

在这种情况下,Func<IQueryService>实际上是一个伪装的抽象工厂。所以问题确实是:“你为什么要使用工厂而不是注入对象?”

当这样的实例的生命周期对消费者很重要时,您需要使用工厂,您需要控制该实例的生命周期,或者创建实例的代价很高。这方面的好例子是对象实现IDisposable时。一次性物品通常需要明确控制。

我个人并不喜欢将Func<T>个委托作为工厂使用,因为它会使您的代码不那么明确。让这个类依赖于Func<IQueryService>,而不是依赖于IQueryServiceFactory。这使您的代码更加明确。当然,这种方法的缺点是你必须编写更多代码(不多,但仍然如此)。

第二个构造函数使用依赖注入模式。但是,第一个构造函数是Poor Man's DI的示例。这是一种允许为单元测试注入依赖项的方法,但是节省了为生产代码使用依赖注入框架的需要。这种方法的缺点是需要依赖容器(在您的情况下为Factory类),这种模式称为Service Locator。另一个缺点是它使一个类所需的依赖性不太明显。