铸造界面和MEF

时间:2009-03-13 10:28:58

标签: vb.net interface mef

我对MEF有以下问题:

主机使用的接口定义:

Public Interface IExecuteDoSomething
   Inherits IAddinSettings

   Event DataReceived As EventHandler(Of DataReceivedEventArgs)
   Function DoSomething() As Boolean

End Interface

Public Class DataReceivedEventArgs
   Inherits EventArgs

   Public Sub New(ByVal message As String)
      Me.Message = message
   End Sub

   Public Message As String
End Class

主机内部其他代码所需的额外接口:

    Public Interface IAddinSettings
        ReadOnly Property Setting() As AddinSettings
    End Interface

    Public Class AddinSettings
        Private _Name As String
        Public Property Name() As String
            Get
                Return _Name
            End Get
            Set(ByVal value As String)
                _Name = value
            End Set
        End Property

        Public Sub New(ByVal name As String)
            Me.Name = name
        End Sub
    End Class

提供导出的类:

    <Export(GetType(SharedLibrary.IExecuteDoSomething))> Public Class Class1
        Implements SharedLibrary.IExecuteDoSomething
        Implements SharedLibrary.IAddinSettings

        Private _Addinsettings As New SharedLibrary.Addinsettings("Test")

        Public Function DoSomething() As Boolean Implements SharedLibrary.IExecuteDoSomething.DoSomething
            MsgBox("i did something")
            Return True
        End Function


        Public Event DataReceived(ByVal sender As Object, ByVal e As SharedLibrary.DataReceivedEventArgs) Implements SharedLibrary.IExecuteDoSomething.DataReceived

        Public ReadOnly Property Setting() As SharedLibrary.AddinSettings Implements SharedLibrary.IAddinSettings.Setting
            Get
                Return  _Addinsettings
            End Get
        End Property
    End Class

主持人:

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim catalog As New Hosting.AggregateCatalog
        Dim d As New Hosting.DirectoryCatalog("..path to dlll..")
        catalog.Catalogs.Add(d)
        Dim container = New Hosting.CompositionContainer(catalog)
        Dim batch As New Hosting.CompositionBatch
        batch.AddPart(Me)
        container.Compose(batch)
        For Each dd In dos
            AddHandler dd.DataReceived, AddressOf testevent
        Next
    End Sub

    <Import()> Public dos As IEnumerable(Of SharedLibrary.IExecuteDoSomething)

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        For Each d In dos
            d.DoSomething()
        Next
    End Sub

    Private Sub testevent(ByVal sender As Object, ByVal e As SharedLibrary.DataReceivedEventArgs)
        MsgBox("Event received: " & e.Message)
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dosomethingelse(DirectCast(dos, System.Collections.Generic.List(Of SharedLibrary.IAddinSettings))) 
    End Sub
    Private Sub Dosomethingelse(byval settings as IEnumerable(Of SharedLibrary.IAddinSettings))
    End Sub 

End Class

在执行Button2_Click例程之前,一切似乎都能正常工作,然后抛出InvalidCastException并显示以下信息:
无法转换类型为'System.Collections.Generic.List 1[SharedLibrary.IExecuteDoSomething]' to type 'System.Collections.Generic.List 1 [SharedLibrary.IAddinSettings]'的对象。

我如何解决这个问题,因为导入的对象实现了这两个接口?

1 个答案:

答案 0 :(得分:1)

我怀疑你实际上遇到了协方差问题 - 这就是这类问题的典型原因。即使List<IFoo>延长List<IBar>IBar 也不 IFoo

如果您使用的是.NET 3.5,在您的情况下解决此问题的最简单方法是删除DirectCast,而是使用Enumerable.Cast

Dosomethingelse(dos.Cast(Of SharedLibrary.IAddinSettings))