为什么来自 Unity.Wcf 的服务主机无法正确解析服务实例?

Why can't service host from Unity.Wcf resolve service's instance correctly?

我有一个统一容器:

var unityContainer = new UnityContainer();

配置如下:

unityContainer.RegisterType<IExampleDomainService, ExampleDomainService>();

unityContainer.RegisterType<IExampleWebService, ExampleWebService>();

ExampleWebService 类型及其构造函数如下所示:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class ExampleWebService
{
    public ExampleWebService(IExampleDomainService exampleDomainService)
    {
        this.exampleDomainService = exampleDomainService;
    }

// ...

ExampleDomainService没有定义构造函数(当我为这种类型显式定义一个无参数构造函数时,问题是一样的)。

接下来,如 Unity.Wcf 的 documentation 中所述:

If you are hosting your WCF service within a Windows Service using a ServiceHost, replace the ServiceHost instance with the custom Unity.Wcf.UnityServiceHost. You will find that the UnityServiceHost takes in a Unity container as its first parameter but is otherwise identical to the default ServiceHost.

我执行以下操作:

 var host = new UnityServiceHost(unityContainer, typeof(ExampleWebService), baseAddress);

然而,这会抛出 System.InvalidOperationException 并显示以下消息:

The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor. To fix the problem, add a default constructor to the type, or pass an instance of the type to the host.

查看 UnityServiceHost implementation at GitHub 它将给定的 serviceType(在本例中为 typeof(ExampleWebService))直接传递给 WCF 的本机 ServiceHost:

public sealed class UnityServiceHost : ServiceHost
{
    public UnityServiceHost(IUnityContainer container, Type serviceType, params Uri[] baseAddresses)
      : base(serviceType, baseAddresses)
             ^^^^^^^^^^^
             ???????????

这显然会崩溃,因为 ServiceHost 对 Unity 及其容器一无所知,并且在缺少无参数构造函数时无法应对。

Unity.Wcf 是否因 non-WAS/non-IIS 托管而完全崩溃,或者(我希望)我做的事情完全错误?

对不起,我不能告诉你为什么你有异常,但我希望能帮助你。

  1. ServiceHost 不需要了解任何关于 Unity 的知识。 DI 通过 实施 IInstanceProvider 并为每个注册 服务行为
  2. 它对我有用,这是非常基本的应用程序 哪个工作正常,也许你可以找到你的问题所在 边

    public class Program
    {
        static void Main(string[] args)
        {
            var container = new UnityContainer();
            container.RegisterType<IDependency, Dependency>();
            container.RegisterType<IHelloWorldService, HelloWorldService>();
            Uri baseAddress = new Uri("http://localhost:8080/hello");
            using (ServiceHost host = new UnityServiceHost(container, typeof(HelloWorldService), baseAddress))
            {
                ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
                smb.HttpGetEnabled = true;
                smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
                host.Description.Behaviors.Add(smb);
    
                host.Open();
    
                Console.WriteLine("The service is ready at {0}", baseAddress);
                Console.WriteLine("Press <Enter> to stop the service.");
                Console.ReadLine();
    
                host.Close();
            }
        }
    }
    
    [ServiceContract]
    public interface IHelloWorldService
    {
        [OperationContract]
        string SayHello(string name);
    }
    
    public interface IDependency
    {
    
    }
    
    public class Dependency : IDependency { }
    
    public class HelloWorldService : IHelloWorldService
    {
        private readonly IDependency _dependency;
    
        public HelloWorldService(IDependency dependency)
        {
            _dependency = dependency;
        }
    
        public string SayHello(string name)
        {
            return string.Format("Hello, {0}", name);
        }
    }
    
  3. 如果使用 InstanceContextMode.Single,WCF 不会调用 InstanceProvider。这就是 Unity.WCF 不能使用它的原因。详细答案可见here.