为什么来自 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 托管而完全崩溃,或者(我希望)我做的事情完全错误?
对不起,我不能告诉你为什么你有异常,但我希望能帮助你。
ServiceHost
不需要了解任何关于 Unity 的知识。 DI 通过
实施 IInstanceProvider
并为每个注册
服务行为
它对我有用,这是非常基本的应用程序
哪个工作正常,也许你可以找到你的问题所在
边
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);
}
}
如果使用 InstanceContextMode.Single
,WCF 不会调用 InstanceProvider
。这就是 Unity.WCF 不能使用它的原因。详细答案可见here.
我有一个统一容器:
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 theServiceHost
instance with the customUnity.Wcf.UnityServiceHost
. You will find that theUnityServiceHost
takes in a Unity container as its first parameter but is otherwise identical to the defaultServiceHost
.
我执行以下操作:
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 托管而完全崩溃,或者(我希望)我做的事情完全错误?
对不起,我不能告诉你为什么你有异常,但我希望能帮助你。
ServiceHost
不需要了解任何关于 Unity 的知识。 DI 通过 实施IInstanceProvider
并为每个注册 服务行为它对我有用,这是非常基本的应用程序 哪个工作正常,也许你可以找到你的问题所在 边
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); } }
如果使用
InstanceContextMode.Single
,WCF 不会调用InstanceProvider
。这就是 Unity.WCF 不能使用它的原因。详细答案可见here.