首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WCF自定义ServiceBehavior/InstanceProvider无参数构造函数

WCF自定义ServiceBehavior/InstanceProvider无参数构造函数
EN

Stack Overflow用户
提问于 2011-01-13 17:58:14
回答 2查看 5.1K关注 0票数 1

我们试图为WCF服务使用依赖注入。该服务依赖于统一容器。容器用于查找实现IJob接口的适当类(基于方法调用中的JobKey参数)并在其上调用方法。

该服务托管在MVC2中。我已经从下面的片段中省略了尽可能多的无关的内容。如果需要的话可以使用完整的代码。

我到目前为止所做的事:

基于这个MSDN条款,我创建了一个自定义InstanceProvider,它应该实例化我的服务并传递给它一个容器。

然后,我创建了一个非常简单的ServiceBehavior来使用InstanceProvider,最后创建了一个只返回ServiceBehaviorBehaviorExtension

代码语言:javascript
复制
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

代码语言:javascript
复制
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

最后,真正点头的BehaviorExtension:

代码语言:javascript
复制
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:

代码语言:javascript
复制
  <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:提供的服务类型不能作为服务加载,因为它没有默认(无参数)构造函数。若要解决此问题,请向该类型添加默认构造函数,或将该类型的实例传递给主机。

代码语言:javascript
复制
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 -默认ServiceBehavior的InstaceProvider不能实例化服务,这是有意义的。

需要注意的是:如果我向我的服务添加了一个无参数构造函数,我就不会得到异常(当然,我也不会传递一个容器),所以我很有信心找到了问题的根源

有人能指出我做错了什么吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-01-13 18:09:06

我想问题是在<service name="WebJobService">.服务元素中不包含behaviorConfiguration。另外,name属性通常必须包含带有名称空间的类型名称。因此,在您的情况下,应该是MyApplication.WebJobService

您还可以查看这些文章中的替代实现12

票数 1
EN

Stack Overflow用户

发布于 2011-01-13 18:09:15

我会简化这个问题。这与团结无关,而是实例化服务并将参数传递给构造函数。如果这是一个问题,请考虑使用性能注入

我通常会让服务实例化统一容器,这样就完全避免了这个问题。

“扫描程序集并填充容器的代码”使其听起来更适合您,而不是MEF

编辑:,我认为我推荐属性注入是错误的。您根本不想让Unity创建服务的实例。因为UnityContainer.Resolve是线程安全的 (尽管配置需要锁定),所以您可以让服务创建并拥有容器的静态实例。容器实例将解析其他依赖项。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4683413

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档