2009-03-13 7 views
0

J'ai le problème suivant avec MEF:interfaces de coulée et MEF

définition d'interface à utiliser par l'hôte:

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 

l'interface supplémentaire nécessaire par un autre code à l'intérieur de l'hôte:

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 

La classe fournissant l'exportation:

<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 

L'hôte:

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 

Tout semble fonctionner très bien jusqu'à ce que la routine Button2_Click est exécuté, un InvalidCastException est jeté avec l'info:
Impossible de jeter l'objet de type « System.Collections.Generic.List 1[SharedLibrary.IExecuteDoSomething]' to type 'System.Collections.Generic.List 1 [SharedLibrary.IAddinSettings] '.

Comment puis-je résoudre ce problème, car l'objet importé implémente les deux interfaces?

Répondre

1

Je suppose que vous êtes en train de rencontrer un problème de covariance - c'est la cause typique de problèmes comme celui-ci. Un List<IFoo> est et non un List<IBar> même si IBar s'étend IFoo.

Si vous utilisez .NET 3.5, la meilleure façon de contourner cela dans votre cas est d'enlever la DirectCast et au lieu d'utiliser Enumerable.Cast:

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

Merci, si vous mentionnez le, est-il plus simple un autre? J'ai déjà lu quelque chose à propos de enumerable.cast et le conseil était d'éviter cela (runtime convertion?) – Johan

+0

La conversion * a * pour être une runtime, en raison de l'incompatibilité des deux types de liste. Quelqu'un * pourrait * avoir ajouté une implémentation de IExecuteDoSomething qui n'implémente pas IAddinSettings. –

+0

Merci beaucoup, semble travailler avec la distribution, peut continuer à coder maintenant ... – Johan