Phi*_*ray 5 .net vb.net mef visual-studio-2012
我在Windows服务中的MEF组合中遇到了问题
以下类是继承自的部分类 System.ServiceProcess.ServiceBase
Imports System.ServiceProcess
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class svc_EpmsOPCService_6Cylinder_Zone1
    Inherits System.ServiceProcess.ServiceBase
    'UserService overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                If _catelog IsNot Nothing Then _catelog.Dispose()
                If _mefContainer IsNot Nothing Then _mefContainer.Dispose()
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub
    ' The main entry point for the process
    <MTAThread()> _
    Shared Sub Main()
#If Not Debug Then
        Dim ServicesToRun() As System.ServiceProcess.ServiceBase
        ServicesToRun = New System.ServiceProcess.ServiceBase() {New svc_EpmsOPCService_6Cylinder_Zone1}
        System.ServiceProcess.ServiceBase.Run(ServicesToRun)
#Else
        Dim service = New Worker
        service.InitWork()
#End If
    End Sub
    'Required by the Component Designer
    Private components As System.ComponentModel.IContainer
    ' NOTE: The following procedure is required by the Component Designer
    ' It can be modified using the Component Designer.  
    ' Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        components = New System.ComponentModel.Container()
        Me.ServiceName = "JCB.EpmsOPCService_6Cylinder_Zone1"
    End Sub
End Class
Imports System.ComponentModel.Composition
Imports System.ComponentModel.Composition.Hosting
Imports Service.Common
Public Class svc_EpmsOPCService_6Cylinder_Zone1
    Private _catelog As AssemblyCatalog
    Private _mefContainer As CompositionContainer
    <Import(GetType(IServiceWorker))>
    Private Property ServiceWorker As IServiceWorker
    Public Sub New()
        ' This call is required by the designer.
        InitializeComponent()
        ' Add any initialization after the InitializeComponent() call.
        Dim catelog As AggregateCatalog = New AggregateCatalog(New DirectoryCatalog("."), New AssemblyCatalog(Reflection.Assembly.GetExecutingAssembly().CodeBase))
        _mefContainer = New CompositionContainer(_catelog)
        _mefContainer.ComposeParts(Me)
    End Sub
    Protected Overrides Sub OnStart(ByVal args() As String)
        ServiceWorker.InitWork()
    End Sub
    Protected Overrides Sub OnStop()
        ServiceWorker.StopWork()
        _mefContainer.Dispose()
    End Sub
End Class
我遇到的问题是当MEF尝试在IServiceWorker属性上运行组合时失败.最初我虽然IServiceWorker不是作为其中一个可用部分而来的AggregateCatalog
Dim catelog As AggregateCatalog = New AggregateCatalog(New DirectoryCatalog("."), New AssemblyCatalog(Reflection.Assembly.GetExecutingAssembly().CodeBase))
为了确认这是一个有效的部分,我使用下面的代码将部件集合输出到文本文件.
For Each p As System.ComponentModel.Composition.Primitives.ComposablePartDefinition In catelog.Parts
    System.IO.File.AppendAllText(compositionErrorLog, String.Concat(vbCrLf, p.ToString, vbCrLf), Text.Encoding.Unicode)
    For Each meta As KeyValuePair(Of String, Object) In p.Metadata
        System.IO.File.AppendAllText(compositionErrorLog, String.Concat("Meta Data Key : ", meta.Key, vbCrLf), Text.Encoding.Unicode)
        System.IO.File.AppendAllText(compositionErrorLog, String.Concat("Meta Data Val : ", meta.Value.ToString, vbCrLf), Text.Encoding.Unicode)
    Next
    For Each exp As Primitives.ExportDefinition In p.ExportDefinitions
        System.IO.File.AppendAllText(compositionErrorLog, String.Concat("Export Definition Contract Name : ", exp.ContractName, vbCrLf), Text.Encoding.Unicode)
    Next
    For Each imp As Primitives.ImportDefinition In p.ImportDefinitions
        System.IO.File.AppendAllText(compositionErrorLog, String.Concat("Import Definition Contract Name : ", imp.ContractName, vbCrLf), Text.Encoding.Unicode)
    Next
    System.IO.File.AppendAllText(compositionErrorLog, vbCrLf, Text.Encoding.Unicode)
Next
您可以从下面的摘录中看到该Service_EPMS_OPC_6Cylinder_Zone1.Worker部件IServiceWorker在其中实现ExportDefinitions
Service.Common.DataAccess.AuditLogger
Export Definition Contract Name : Service.Common.DataAccess.IAuditLogger
Import Definition Contract Name : Service.Common.DataAccess.IDatabaseHelperFactory
Service.Common.DataAccess.DataHelper
Export Definition Contract Name : Service.Common.DataAccess.IDataHelper
Import Definition Contract Name : Service.Common.DataAccess.IDatabaseHelperFactory
Service.Common.DataAccess.SqlDatabaseHelperFactory
Export Definition Contract Name : Service.Common.DataAccess.IDatabaseHelperFactory
Service.Common.Logging.ErrorLogger
Export Definition Contract Name : Service.Common.Logging.ILogger
Import Definition Contract Name : Service.Common.DataAccess.IDataHelper
Service.Common.Network.NetworkAvailability
Export Definition Contract Name : Service.Common.Network.INetworkAvailability
Import Definition Contract Name : Service.Common.DataAccess.IDataHelper
Import Definition Contract Name : Service.Common.Network.IRemoteServiceHost
Service.Common.Network.RemoteServiceHost
Export Definition Contract Name : Service.Common.Network.IRemoteServiceHost
Service.Common.ObjectCreation.EngineBuilder
Export Definition Contract Name : Service.Common.ObjectCreation.IEngineBuilder
Import Definition Contract Name : Service.Common.DataAccess.IDataHelper
Service.Common.Opc.OpcHelper
Export Definition Contract Name : Service.Common.Opc.IOpcHelper
Service_EPMS_OPC_6Cylinder_Zone1.Worker
Export Definition Contract Name : Service.Common.IServiceWorker
Service_EPMS_OPC_6Cylinder_Zone1.ZoneProcess
Export Definition Contract Name : Service.Common.IZoneProcess
Import Definition Contract Name : Service.Common.Logging.ILogger
Import Definition Contract Name : Service.Common.DataAccess.IDataHelper
Import Definition Contract Name : Service.Common.Network.INetworkAvailability
Import Definition Contract Name : Service.Common.ObjectCreation.IEngineBuilder
Import Definition Contract Name : Service.Common.Opc.IOpcHelper
Import Definition Contract Name : Service.Common.DataAccess.IAuditLogger
这是我所期望的,因为Worker类在类型上执行导出IServiceWorker.我已经在这个类上注释了两个额外的Imports,以确保它们不会导致问题.
Imports System.ComponentModel.Composition
Imports System.ComponentModel.Composition.Hosting
Imports System.Threading
Imports Service.Common
Imports Service.Common.Enums
Imports Service.Common.Logging
<Export(GetType(IServiceWorker))>
Public Class Worker
    Implements IServiceWorker
    Private _thread As Thread
    '<Import(GetType(IZoneProcess))>
    'Private Property Processor() As IZoneProcess
    '<Import(GetType(ILogger))>
    'Private Property Logger() As ILogger
#Region " Service Methods"
    ''' <summary>
    ''' Tear down the service
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub StopWork() Implements IServiceWorker.StopWork
        'Tear down the worker thread
        If Not _thread Is Nothing Then
            If Not _thread.Join(100) Then
                _thread.Abort()
            End If
        End If
    End Sub
    ''' <summary>
    ''' Initialise the worker thread
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub InitWork() Implements IServiceWorker.InitWork
        Dim objThreadStart As New ThreadStart(AddressOf Me.StartWork)
        _thread = New Thread(objThreadStart)
        _thread.Start()
    End Sub
    ''' <summary>
    ''' Start the worker thread functionality
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub StartWork()
        Try
            If Not Initialise() Then
                Me.StopWork()
            End If
        Catch ex As Exception
            ' If Logger IsNot Nothing Then Logger.LogError(My.Settings.ApplicationID, "StartWork", ex.Message, IssueSeverity.Critical)
            Me.StopWork()
        End Try
    End Sub
#End Region
    Private Function Initialise() As Boolean
#If DEBUG Then
        RunDebugModeComposition()
#End If
        'Return Processor.InitialiseApplication()
    End Function
    Private Sub RunDebugModeComposition()
        Try
            Dim catelog As AggregateCatalog = New AggregateCatalog(New DirectoryCatalog("."), New AssemblyCatalog(Reflection.Assembly.GetExecutingAssembly().CodeBase))
            Dim container As CompositionContainer = New CompositionContainer(catelog)
            container.ComposeParts(Me)
        Catch ex As CompositionException
            Throw New ApplicationException("The composition of the application failed. Pleae check the underlying exception", ex)
        End Try
    End Sub
End Class
我用下面的代码进一步查询了Composition问题
Try
    _mefContainer.ComposeParts(Me)
Catch ex As CompositionException
    For Each e As CompositionError In ex.Errors
        System.IO.File.AppendAllText(compositionErrorLog, String.Concat(vbCrLf, "Description : ", e.Description, vbCrLf), Text.Encoding.Unicode)
        System.IO.File.AppendAllText(compositionErrorLog, String.Concat(vbCrLf, "Message : ", e.Exception.Message, vbCrLf), Text.Encoding.Unicode)
        System.IO.File.AppendAllText(compositionErrorLog, String.Concat(vbCrLf, "Stack Trace : ", e.Exception.StackTrace, vbCrLf), Text.Encoding.Unicode)
        If e.Exception.InnerException IsNot Nothing Then
            System.IO.File.AppendAllText(compositionErrorLog, String.Concat(vbCrLf, "Message : ", e.Exception.InnerException.Message, vbCrLf), Text.Encoding.Unicode)
            System.IO.File.AppendAllText(compositionErrorLog, String.Concat(vbCrLf, "Stack Trace : ", e.Exception.InnerException.StackTrace, vbCrLf), Text.Encoding.Unicode)
        End If
    Next
End Try
这个游戏我在文本文件中输出如下
Description : Cannot set import 'Service_EPMS_OPC_6Cylinder_Zone1.svc_EpmsOPCService_6Cylinder_Zone1.ServiceWorker (ContractName="Service.Common.IServiceWorker")' on part 'Service_EPMS_OPC_6Cylinder_Zone1.svc_EpmsOPCService_6Cylinder_Zone1'.
Message : The composition produced a single composition error. The root cause is provided below. Review the CompositionException.Errors property for more detailed information.
1) No exports were found that match the constraint: 
    ContractName    Service.Common.IServiceWorker
    RequiredTypeIdentity    Service.Common.IServiceWorker
Stack Trace : 
现在我不确定的是为什么IServiceWorkerMEF Catelog Parts集合中的Export没有得到ComposeParts.据我所知,Worker类的Export属性应与ServiceWorker属性中的Import匹配svc_EpmsOPCService_6Cylinder_Zone1
知道为什么这个导入不起作用?
编辑:我重构了代码,以便'Worker'类被称为具体实现,然后组合在'Worker'类中进行,一切正常.是否有限制,你不能从继承自'System.ServiceProcess.ServiceBase'的Windows服务组件组成MEF部分?
迟到了,但我想知道这个问题是否与 Windows 如何注册和维护服务更相关。我相信 SCM 或其他后端服务组件在注册服务时会锁定资源。
我不认为这是服务基类本身的问题,它看起来并不太奇怪,它不是静态的,它只是扩展了组件等。相反,我打赌它与服务本身有关资源管理。
哈哈,您是否在 MEF DirectoryCatalog 中使用 ShadowCopy?如果你没有,我想知道它是否会有帮助......其中一些是猜测,因为我没有时间设置自己的测试床,但这是根据分别使用 MEF 和服务的经验进行的有根据的猜测。
| 归档时间: | 
 | 
| 查看次数: | 841 次 | 
| 最近记录: |