C# 如果提供了提供程序,为什么ServiceHost需要类类型?

C# 如果提供了提供程序,为什么ServiceHost需要类类型?,c#,wcf,dependency-injection,C#,Wcf,Dependency Injection,我有一个控制台主机应用程序。在这里,我使用IoC容器作为实例的提供者,并希望将契约接口传递给ServiceHost构造函数。 显然,它说我不能使用接口 为什么ServiceHost甚至需要它?我附加自定义提供程序,如果他想实例化它!更重要的是,我不想将实例传递给它——它应该是按需传递的 如何使ServiceHost仅从接口(请记住IoC中已经存在的所有必要绑定) 例如: var host = new ServiceHost(typeof(IMyContract), address); 因此,基

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

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

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

例如:

var host = new ServiceHost(typeof(IMyContract), address);
因此,基本上,通过指定InstanceProvider,您应该获得这种行为。但是微软强制要求具体的实现类型,即使我提供了实例工厂,也可能没有具体的实现类型

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

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

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class Service : IService
{
    // ...
}
结论 现在,您可以使用任何想要创建服务的注入容器,并且您的服务甚至可以有一个带参数的构造函数

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

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

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class Service : IService
{
    // ...
}
结论 现在,您可以使用任何想要创建服务的注入容器,并且您的服务甚至可以有一个带参数的构造函数

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

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


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

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

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



一种让它搜索的方法是通过实现它,它将知道如何解析传入实例的类型。

也许一个代码示例会有帮助,让您的问题更清楚。添加了代码示例。我猜这就是您正在使用的WCF?你应该把它弄清楚。还要说明您正在使用的IoC容器。如果您使用的是WCF和Unity,请查看和。可以找到NuGet软件包。您可能误解了。IoC basicali意味着依赖项解析,所以我想通过只指定特定类型的合同接口来解析特定类型上的ServiceHost依赖项。换句话说,InstanceProvider应该自己做,而不是通过从构造函数中抛出一些愚蠢的异常来实现ServiceHost。也许一个代码示例会有帮助,让您的问题更清楚。添加了代码示例。我猜这就是您正在使用的WCF?你应该把它弄清楚。还要说明您正在使用的IoC容器。如果您使用的是WCF和Unity,请查看和。可以找到NuGet软件包。您可能误解了。IoC basicali意味着依赖项解析,所以我想通过只指定特定类型的合同接口来解析特定类型上的ServiceHost依赖项。换句话说,InstanceProvider应该自己完成,而不是通过从构造函数抛出一些愚蠢的异常来实现ServiceHost。你们不理解这个问题。IoC的主要原因是隐藏具体的实现并延迟加载一些依赖项。通过在ServiceHost构造函数中指定类型或实例,您破坏了这一原则之一。这是不正确的。您可以通过接口参数轻松地将服务实例传递给ViewModel构造函数(或承载服务的任何类),并将其传递给ServiceHost。我在回答中添加了一个示例。谢谢,现在我明白了,您创建了引导类。但是,懒惰呢?当你开始30次服务时,它会带来很大的伤害。记住,服务主机只在实际需要时创建服务实例。如果DI容器自己创建服务类,它基本上什么都不做(在我的例子中,构造函数几乎是空的)。只有当ServiceHost打开时,服务才会在网络上侦听传入的请求。是的,如果有人触摸它的API,服务就会创建实例,当然是通过默认工厂。但在本例中,您将在应用程序启动时加载传递到服务构造函数中的所有内容。这是冷启动问题。你们不理解这个问题。IoC的主要原因是隐藏具体的实现并延迟加载一些依赖项。通过在ServiceHost构造函数中指定类型或实例,您破坏了这一原则之一。这是不正确的。您可以通过接口参数轻松地将服务实例传递给ViewModel构造函数(或承载服务的任何类),并将其传递给ServiceHost。我在回答中添加了一个示例。谢谢,现在我明白了,您创建了引导类。但是,懒惰呢?当你开始30次服务时,它会带来很大的伤害。请记住,服务主机仅在实际需要时创建服务实例
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();
        // ...
    }
}