Мы пытаемся использовать Dependency Injection для службы WCF.Служба зависит от контейнера Unity.Контейнер используется для поиска соответствующего класса, который реализует интерфейс IJob
(основанный на параметре JobKey
в вызове метода) и вызывает для него метод.
Сервис размещается в MVC2.Я опустил как можно больше ненужных вещей из приведенных ниже фрагментов.Полный код доступен, если требуется ...
Что я уже сделал:
Основываясь на этой статье MSDN , я создал пользовательский InstanceProvider
, которыйЯ должен создать экземпляр моего сервиса и передать ему контейнер.
Затем я создал очень noddy ServiceBehavior
для использования InstanceProvider
и, наконец, BehaviorExtension
, который просто возвращает ServiceBehavior
.
Public Class WCFDIInstanceProvider
Implements IInstanceProvider
Private ServiceType As Type
Private Property _Container As IUnityContainer
Private ReadOnly Property Container As IUnityContainer
Get
If _Container Is Nothing Then
_Container = InitialiseContainer()
End If
Return _Container
End Get
End Property
Public Sub New(ByVal ServiceType As Type)
Me.ServiceType = ServiceType
End Sub
Private Function InitialiseContainer() As IUnityContainer
'Code which scans assemblies and populates the container as appropriate
'I'm confident this code works as I've tested it elsewhere
Return Container
End Function
Public Function GetInstance(ByVal instanceContext As System.ServiceModel.InstanceContext) As Object Implements System.ServiceModel.Dispatcher.IInstanceProvider.GetInstance
Return GetInstance(instanceContext, Nothing)
End Function
Public Function GetInstance(ByVal instanceContext As System.ServiceModel.InstanceContext, ByVal message As System.ServiceModel.Channels.Message) As Object Implements System.ServiceModel.Dispatcher.IInstanceProvider.GetInstance
Return Container.Resolve(Me.ServiceType)
End Function
End Class
И ServiceBehavior
:
Public Class WCFDIServiceBehavior
Implements IServiceBehavior
Public Sub ApplyDispatchBehavior(ByVal serviceDescription As System.ServiceModel.Description.ServiceDescription, ByVal serviceHostBase As System.ServiceModel.ServiceHostBase) Implements System.ServiceModel.Description.IServiceBehavior.ApplyDispatchBehavior
For Each ChannelDispatcherBase As ChannelDispatcherBase In serviceHostBase.ChannelDispatchers
Dim ChannelDispatcher As ChannelDispatcher = TryCast(ChannelDispatcherBase, ChannelDispatcher)
If ChannelDispatcher IsNot Nothing Then
For Each Dispatcher As EndpointDispatcher In ChannelDispatcher.Endpoints
Dispatcher.DispatchRuntime.InstanceProvider = New WCFDIInstanceProvider(serviceDescription.ServiceType)
Next
End If
Next
End Sub
И, наконец, действительно noddy BehaviorExtension:
Public Class WCFDIBehaviorExtension
Inherits BehaviorExtensionElement
Public Overrides ReadOnly Property BehaviorType As System.Type
Get
Return GetType(WCFDIServiceBehavior)
End Get
End Property
Protected Overrides Function CreateBehavior() As Object
Return New WCFDIServiceBehavior
End Function
End Class
Инструмент WCF Config, кажется, нравится всемиз вышеупомянутого и сгенерировал следующий Config XML:
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"
aspNetCompatibilityEnabled="true">
<serviceActivations>
<add relativeAddress="WebJob.svc"
service="MyApplication.WebJobService"
factory="System.ServiceModel.Activation.ServiceHostFactory" />
</serviceActivations>
</serviceHostingEnvironment>
<standardEndpoints>
<mexEndpoint>
<standardEndpoint name="WebJobServiceMex" />
</mexEndpoint>
</standardEndpoints>
<behaviors>
<serviceBehaviors>
<behavior name="WCFDIServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<WCFDIBehavior />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="WebJobService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="httpBinding"
name="HTTPEndpoint" contract="MyApplication.JobService.Common.IWebJobService" />
<endpoint binding="mexTcpBinding" bindingConfiguration="" name="mexEndpoint" />
</service>
</services>
Исключение, которое я получаю:
System.ServiceModel.ServiceActivationException: Служба '/MyAppDir/WebJob.svc 'невозможно активировать из-за исключения во время компиляции.Сообщение об исключении: Предоставленный тип сервиса не может быть загружен как сервис, потому что у него нет конструктора по умолчанию (без параметров).Чтобы устранить проблему, добавьте конструктор по умолчанию к типу или передайте экземпляр типа на хост.
System.InvalidOperationException: предоставленный тип сервиса не может быть загружен как сервис, потому что он не имеетконструктор по умолчанию (без параметров).Чтобы решить эту проблему, добавьте конструктор по умолчанию к типу или передайте экземпляр типа на хост.
WebHost failed to process a request.
Sender Information: System.ServiceModel.ServiceHostingEnvironment+HostingManager/13982700
Exception: System.ServiceModel.ServiceActivationException: The service '/MyAppDir/WebJob.svc' cannot be activated due to an exception during compilation. The exception message is: 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.. ---> 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.
at System.ServiceModel.Dispatcher.InstanceBehavior..ctor(DispatchRuntime dispatch, ImmutableDispatchRuntime immutableRuntime)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime..ctor(DispatchRuntime dispatch)
at System.ServiceModel.Dispatcher.DispatchRuntime.GetRuntimeCore()
at System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpened()
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout)
[Blah]
Process Name: w3wp
Process ID: 2108
Это имеет смысл, если не применять мой пользовательский ServiceBehavior
-InstaceProvider из ServiceBehavior по умолчанию не может создать экземпляр службы.
Некоторые вещи, на которые следует обратить внимание: если я добавляю конструктор без параметров в свою службу, я не получаю исключения (но, конечно, я не получаюили контейнер), так что я вполне уверен, что нашел источник проблемы
Может кто-нибудь указать, что я делаю неправильно?