【问题标题】:Why ServiceHost need class type if provider were given?如果给定提供者,为什么 ServiceHost 需要类类型?
【发布时间】:2016-07-22 09:00:24
【问题描述】:

我有控制台主机应用程序。在这里,我使用 IoC 容器作为实例的提供者,并希望将合约接口传递给 ServiceHost 构造函数。 显然,它说我不能用接口来做。

为什么 ServiceHost 甚至需要它?如果他想实例化它,我会附加自定义提供程序!更重要的是,我不想将实例传递给它——它应该是按需的。

如何仅从接口创建 ServiceHost(记住 IoC 中已经存在的所有必要绑定)?

例子:

var host = new ServiceHost(typeof(IMyContract), address);

因此,基本上,通过指定 InstanceProvider 您应该获得此行为。但是微软强制要求提供具体的实现类型,即使我提供了实例工厂并且可能没有具体的实现类型!

【问题讨论】:

  • 也许一个代码示例会有所帮助并使您的问题更清楚。
  • 添加代码示例。
  • 我猜这是您正在使用的 WCF?你应该清除它。还有你正在使用哪个 IoC 容器。如果您使用的是 WCF 和 Unity,请查看 thisthis。 NuGet 包可以在here找到。
  • 你可能误会了。 IoC 基本上意味着依赖解析,所以我想通过仅指定它的合同接口来解决对特定类型的 ServiceHost 依赖。换句话说,InstanceProvider 应该只能自己做,而不是 ServiceHost 通过从构造函数中抛出一些愚蠢的异常。

标签: c# wcf dependency-injection


【解决方案1】:

原因很简单,ServiceHost 内部有一个方法 CreateImplmentation,它将调用传入类型的默认构造函数。

当您将接口作为类型传递时,没有可调用的构造函数。它不会自动在您的程序中搜索接口的危害,您的代码(或您使用的 DI 库)有责任找到这些实现并为它们传递 Type 值。

实现搜索的一种方法是实现a custom IInstanceProvider,它将知道如何解析您传入实例的类型。

【讨论】:

  • 它会在这个类型被传递给提供者之前抛出关于无效接口类型的异常。所以,不,这行不通。
【解决方案2】:

问题

ServiceHost 的构造函数采用类类型或服务的现有实例,其中serviceType 必须是具有无参数构造函数的类

public ServiceHost(Type serviceType, params Uri[] baseAddresses);
public ServiceHost(object singletonInstance, params Uri[] baseAddresses);

解决方案

要使用后一个构造函数,您的服务实现必须用InstanceContextMode.Single 标记为ServiceBehavior

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class Service : IService
{
    // ...
}

结论

现在你可以使用任何你喜欢的注入容器来创建你的服务,你的服务甚至可以有一个带参数的构造函数。

示例

public class DiscoveryService
{
    private readonly IService _service;

    private ServiceHost _serviceHost;

    public DiscoveryService(IService service)
    {
        _service = service;

        // ...
    }

    private void StartServerMode()
    {
        _serviceHost = new ServiceHost(_service);
        _serviceHost.Open();
        // ...
    }
}

【讨论】:

  • 你没听懂问题。 IoC 的主要原因是隐藏具体实现和延迟加载一些依赖项。通过在 ServiceHost 构造函数中指定类型或实例,您会破坏其中的一个原则。
  • 这不正确。您可以通过接口参数轻松地将服务实例传递给 ViewModel 构造函数(或托管服务的任何类)并将其传递给 ServiceHost。我在答案中添加了一个示例。
  • 谢谢,现在我明白了,你创建了引导类。但是,懒惰呢?当您启动约 30 项服务时,可能会受到很大的伤害。请记住,服务主机仅在实际需要时才创建服务实例。
  • 如果 DI 容器自己创建服务类,它基本上什么都不做(在我的例子中,构造函数几乎是空的)。只有当 ServiceHost 打开时,服务才会在网络上监听传入的请求。
  • 是的,如果有人触摸它的 API,将创建实例,当然,通过默认工厂。但在这种情况下,您将加载 everything 在应用程序启动时传递给服务构造函数的内容。这是冷启动问题。
猜你喜欢
  • 2016-11-13
  • 1970-01-01
  • 1970-01-01
  • 2022-06-24
  • 1970-01-01
  • 1970-01-01
  • 2021-08-18
  • 2010-10-03
  • 1970-01-01
相关资源
最近更新 更多