Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 具有无参数构造函数的WCF自定义ServiceBehavior/InstanceProvider_.net_Wcf_Asp.net Mvc 2_.net 4.0_Unity Container - Fatal编程技术网

.net 具有无参数构造函数的WCF自定义ServiceBehavior/InstanceProvider

.net 具有无参数构造函数的WCF自定义ServiceBehavior/InstanceProvider,.net,wcf,asp.net-mvc-2,.net-4.0,unity-container,.net,Wcf,Asp.net Mvc 2,.net 4.0,Unity Container,我们正在尝试对WCF服务使用依赖项注入。该服务依赖于Unity容器。容器用于查找实现IJob接口的适当类(基于方法调用中的JobKey参数),并对其调用方法 该服务正在MVC2中托管。我从下面的片段中尽可能多地省略了不相关的内容。如果需要,完整代码可用 到目前为止我所做的: 基于此,我创建了一个定制的InstanceProvider,它应该实例化我的服务并将其传递给一个容器 然后,我创建了一个非常noddyservicebhavior来使用InstanceProvider,最后是一个Behavi

我们正在尝试对WCF服务使用依赖项注入。该服务依赖于Unity容器。容器用于查找实现
IJob
接口的适当类(基于方法调用中的
JobKey
参数),并对其调用方法

该服务正在MVC2中托管。我从下面的片段中尽可能多地省略了不相关的内容。如果需要,完整代码可用

到目前为止我所做的:

基于此,我创建了一个定制的
InstanceProvider
,它应该实例化我的服务并将其传递给一个容器

然后,我创建了一个非常noddy
servicebhavior
来使用
InstanceProvider
,最后是一个
BehaviorExtension
,它只返回
servicebhavior

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
以及
服务行为

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 behavior扩展:

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配置工具似乎喜欢上述所有内容,并生成了以下配置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>
假设它没有应用我的自定义
ServiceBehavior
,这是有意义的-默认ServiceBehavior的InstaceProvider无法实例化该服务

需要注意的是:如果我在服务中添加一个无参数构造函数,我不会得到异常(当然,我也不会得到一个容器),因此我很有信心我已经找到了问题的根源


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

我想问题出在
服务元素不包含行为配置。此外,“名称”属性通常必须包含带有名称空间的类型名称。因此,在您的情况下,它应该是
MyApplication.WebJobService


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

我会简化这个问题。这与Unity无关,而是实例化服务并将参数传递给构造函数。如果这是一个问题,考虑使用.< /P> 我通常会让服务实例化Unity容器,这样就完全避免了这个问题

“扫描程序集并填充容器的代码”听起来可能比Unity更适合您


编辑:我认为我错误地推荐财产注入。您根本不希望Unity创建服务的实例。因为(尽管配置需要锁定),您可以让服务创建并拥有容器的静态实例。容器实例将解决其他依赖项。

MEF几乎肯定会更适合-不幸的是,该项目是一个新的启动项目,我们的资源有限-切换到MEF将花费开发时间,我们无法节省ATM。不过,我们已经在为以后的版本做准备了——谢谢你指出。我的印象是,服务行为适用于所有服务——这很可能是我的错误,我明天会到办公室检查。至于命名-我认为这只是一个用于从XML中的其他点引用元素的名称?不。您不需要在配置中引用服务设置。该名称将您的服务类型绑定到此设置。至少在开箱即用的实例中,名称必须与具有名称空间的类型名称完全相同,否则将不使用配置。@Steven感谢您的编辑,但我认为异常转储非常清楚-复制引号中的错误消息真的能提高质量吗?是的,我相信能。我通过谷歌搜索异常消息找到了这个问题,但是在扫描了这个问题之后,我找不到这个消息。我的编辑让其他人更容易找到这条消息,这是我的目标。
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