Кастинг интерфейсов и MEF - PullRequest
0 голосов
/ 13 марта 2009

У меня следующая проблема с 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 Ответ

1 голос
/ 13 марта 2009

Я подозреваю, что вы на самом деле сталкиваетесь с проблемой ковариации - это типичная причина таких проблем. A List<IFoo> равно , а не a List<IBar>, даже если IBar расширяется IFoo.

Если вы используете .NET 3.5, самый простой способ обойти это в вашем случае - удалить DirectCast и вместо этого использовать Enumerable.Cast:

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