<ImportMany()> problem

Jul 31, 2009 at 4:15 PM
    I cannot get this to work: can classes that are exported be imported as properties?
What am I doing wrong?
It does not throw any exceptions, the ForEach loop just finds nothing in Macros()
(Main Class)
 
Public Sub Go()
        Compose()
        RunMacro("AnotherGreatMacro")
    End Sub

    Public Sub Compose()
        Dim Dir As [String] = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments), "Extensions")
        Dim Catalog As New DirectoryCatalog(Dir)
        Dim Container As New CompositionContainer(Catalog)
        Container.SatisfyImportsOnce(Me)
    End Sub

    Private _Macros As IEnumerable(Of IMefMacro)
    <ImportMany("IMefMacro")> _
    Private Property Macros() As IEnumerable(Of IMefMacro)
        Get
            Return _Macros
        End Get
        Set(ByVal value As IEnumerable(Of IMefMacro))
            _Macros = value
        End Set
    End Property
    Private Sub RunMacro(ByVal MacroName As String)
        For Each m As IMefMacro In Macros
            If m.Name = MacroName Then
                m.Run(Me, MyParameter)
            End If
        Next
    End Sub

    Public Interface IMefMacro
        ReadOnly Property Name() As String
        ' returns the name of the macro
        Sub Run(ByVal Application As Object, ByVal Contact As Object)
        ' executes the macro
    End Interface
 
(MEF Class)
Imports System.ComponentModel.Composition

Public Class MEFAddIn

    <Export("IMEFMacro")> _
Public Class DoSomethingCoolMacro
        Implements IMefMacro

        Public ReadOnly Property Name() As String Implements IMefMacro.Name
            Get
                Return "DoSomethingCoolMacro"
            End Get
        End Property

        Public Sub Run(ByVal Application As Object, ByVal parameter As Object) Implements IMefMacro.Run
            MsgBox("Bravo")
        End Sub
    End Class

    <Export("IMEFMacro")> _
    Public Class YetAnotherGreatMacro
        Implements IMefMacro

        Public ReadOnly Property Name() As String Implements IMefMacro.Name
            Get
                Return "YetAnotherGreatMacro"
            End Get
        End Property

        Public Sub Run(ByVal Application As Object, ByVal parameter As Object) Implements IMefMacro.Run
            MsgBox("Tango")
        End Sub
    End Class

    Public Interface IMefMacro
        ReadOnly Property Name() As String
        Sub Run(ByVal Application As Object, ByVal parameter As Object)
    End Interface

End Class
 
 
Jul 31, 2009 at 4:53 PM

The [ImporyMany] is asking for all exports named 'IMEFMacro' that are also of type 'IMefMacro'. The exports are saying 'I'm exporting under the name 'IMEFMacro', but of types 'DoSomethingCoolMacro' and 'YetAnotherGreatMacro'.

We don't treat these the same. I would recommend, replacing the string contracts with real types. For example, pass GetType(IMefMacro) to [Export] and to [ImportMany] (although the one to ImportMany is redundant as we automatically calculate from the property return type.

Jul 31, 2009 at 6:32 PM

I tried that, and am still exiting the ForEach loop finding nothing. Any other suggestions?

Jul 31, 2009 at 6:48 PM

The contract names are case-sensitive. You’re using both “IMEFMacro” and “IMefMacro” – these need to be in the same case.

Cheers

Nick

From: BillL [mailto:notifications@codeplex.com]
Sent: Friday, July 31, 2009 10:33 AM
To: Nicholas Blumhardt
Subject: Re: <ImportMany()> problem [MEF:64122]

From: BillL

I tried that, and am still exiting the ForEach loop finding nothing. Any other suggestions?

Read the full discussion online.

To add a post to this discussion, reply to this email (MEF@discussions.codeplex.com)

To start a new discussion for this project, email MEF@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com

Jul 31, 2009 at 8:25 PM

Got that, still not working. Here's the corrected code:

 

MEF Class:

 

Imports System.ComponentModel.Composition

Public Class MEFAddIn

    <Export(GetType(IMefMacro))> _
Public Class DoSomethingCoolMacro
        Implements IMefMacro

        Public ReadOnly Property Name() As String Implements IMefMacro.Name
            Get
                Return "DoSomethingCoolMacro"
            End Get
        End Property

        Public Sub Run(ByVal Application As Object, ByVal parameter As Object) Implements IMefMacro.Run
            MsgBox("Bravo")
        End Sub
    End Class

    <Export(GetType(IMefMacro))> _
    Public Class YetAnotherGreatMacro
        Implements IMefMacro

        Public ReadOnly Property Name() As String Implements IMefMacro.Name
            Get
                Return "YetAnotherGreatMacro"
            End Get
        End Property

        Public Sub Run(ByVal Application As Object, ByVal parameter As Object) Implements IMefMacro.Run
            MsgBox("Tango")
        End Sub
    End Class

    Public Interface IMefMacro
        ReadOnly Property Name() As String
        Sub Run(ByVal Application As Object, ByVal Contact As Object)
    End Interface

End Class
 
 Main Class:
    Public Sub Macro1()
        Compose()
        RunMacro("YetAnotherGreatMacro")
    End Sub

    Public Sub Compose()
        Dim Dir As [String] = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments), "ContactManager\Macros\Extensions")
        Dim Catalog As New DirectoryCatalog(Dir)
        Dim Container As New CompositionContainer(Catalog)
        Container.SatisfyImportsOnce(Me)
    End Sub

    Private _Macros As IEnumerable(Of IMefMacro)
    <ImportMany(GetType(IMefMacro))> _
    Private Property Macros() As IEnumerable(Of IMefMacro)
        Get
            Return _Macros
        End Get
        Set(ByVal value As IEnumerable(Of IMefMacro))
            _Macros = value
        End Set
    End Property
    Private Sub RunMacro(ByVal MacroName As String)
        For Each m As IMefMacro In Macros
            If m.Name = MacroName Then
                m.Run(Me, MyContact)
            End If
        Next
    End Sub

    Public Interface IMefMacro
        ReadOnly Property Name() As String
        Sub Run(ByVal Application As Object, ByVal Contact As Object)
    End Interface

I must be missing something, but I'm not sure what.
Jul 31, 2009 at 9:51 PM

If you examine your catalog under the debugger what do you see?

From: BillL [mailto:notifications@codeplex.com]
Sent: Friday, July 31, 2009 12:26 PM
To: Nicholas Blumhardt
Subject: Re: <ImportMany()> problem [MEF:64122]

From: BillL

Got that, still not working. Here's the corrected code:

MEF Class:

Imports System.ComponentModel.Composition
 
Public Class MEFAddIn
 
    <Export(GetType(IMefMacro))> _
Public Class DoSomethingCoolMacro
        Implements IMefMacro
 
        Public ReadOnly Property Name() As String Implements IMefMacro.Name
            Get
                Return "DoSomethingCoolMacro"
            End Get
        End Property
 
        Public Sub Run(ByVal Application As Object, ByVal parameter As Object) Implements IMefMacro.Run
            MsgBox("Bravo")
        End Sub
    End Class
 
    <Export(GetType(IMefMacro))> _
    Public Class YetAnotherGreatMacro
        Implements IMefMacro
 
        Public ReadOnly Property Name() As String Implements IMefMacro.Name
            Get
                Return "YetAnotherGreatMacro"
            End Get
        End Property
 
        Public Sub Run(ByVal Application As Object, ByVal parameter As Object) Implements IMefMacro.Run
            MsgBox("Tango")
        End Sub
    End Class
 
    Public Interface IMefMacro
        ReadOnly Property Name() As String
        Sub Run(ByVal Application As Object, ByVal Contact As Object)
    End Interface
 
End Class
 
 Main Class:
 
    Public Sub Macro1()
        Compose()
        RunMacro("YetAnotherGreatMacro")
    End Sub
 
    Public Sub Compose()
        Dim Dir As [String] = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments), "ContactManager\Macros\Extensions")
        Dim Catalog As New DirectoryCatalog(Dir)
        Dim Container As New CompositionContainer(Catalog)
        Container.SatisfyImportsOnce(Me)
    End Sub
 
    Private _Macros As IEnumerable(Of IMefMacro)
    <ImportMany(GetType(IMefMacro))> _
    Private Property Macros() As IEnumerable(Of IMefMacro)
        Get
            Return _Macros
        End Get
        Set(ByVal value As IEnumerable(Of IMefMacro))
            _Macros = value
        End Set
    End Property
    Private Sub RunMacro(ByVal MacroName As String)
        For Each m As IMefMacro In Macros
            If m.Name = MacroName Then
                m.Run(Me, MyContact)
            End If
        Next
    End Sub
 
    Public Interface IMefMacro
        ReadOnly Property Name() As String
        Sub Run(ByVal Application As Object, ByVal Contact As Object)
    End Interface
 
I must be missing something, but I'm not sure what.

Read the full discussion online.

To add a post to this discussion, reply to this email (MEF@discussions.codeplex.com)

To start a new discussion for this project, email MEF@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com

Jul 31, 2009 at 10:42 PM

Bill, I am recreating this on my side to debug it. Can you mail me your project? gblock@microsoft.com

Thanks

Glenn

From: nblumhardt [mailto:notifications@codeplex.com]
Sent: Friday, July 31, 2009 1:51 PM
To: Glenn Block
Subject: Re: <ImportMany()> problem [MEF:64122]

From: nblumhardt

If you examine your catalog under the debugger what do you see?

From: BillL [mailto:notifications@codeplex.com]
Sent: Friday, July 31, 2009 12:26 PM
To: Nicholas Blumhardt
Subject: Re: <ImportMany()> problem [MEF:64122]

From: BillL

Got that, still not working. Here's the corrected code:

MEF Class:

Imports System.ComponentModel.Composition
 
Public Class MEFAddIn
 
    <Export(GetType(IMefMacro))> _
Public Class DoSomethingCoolMacro
        Implements IMefMacro
 
        Public ReadOnly Property Name() As String Implements IMefMacro.Name
            Get
                Return "DoSomethingCoolMacro"
            End Get
        End Property
 
        Public Sub Run(ByVal Application As Object, ByVal parameter As Object) Implements IMefMacro.Run
            MsgBox("Bravo")
        End Sub
    End Class
 
    <Export(GetType(IMefMacro))> _
    Public Class YetAnotherGreatMacro
        Implements IMefMacro
 
        Public ReadOnly Property Name() As String Implements IMefMacro.Name
            Get
                Return "YetAnotherGreatMacro"
            End Get
        End Property
 
        Public Sub Run(ByVal Application As Object, ByVal parameter As Object) Implements IMefMacro.Run
            MsgBox("Tango")
        End Sub
    End Class
 
    Public Interface IMefMacro
        ReadOnly Property Name() As String
        Sub Run(ByVal Application As Object, ByVal Contact As Object)
    End Interface
 
End Class
 
 Main Class:
 
    Public Sub Macro1()
        Compose()
        RunMacro("YetAnotherGreatMacro")
    End Sub
 
    Public Sub Compose()
        Dim Dir As [String] = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments), "ContactManager\Macros\Extensions")
        Dim Catalog As New DirectoryCatalog(Dir)
        Dim Container As New CompositionContainer(Catalog)
        Container.SatisfyImportsOnce(Me)
    End Sub
 
    Private _Macros As IEnumerable(Of IMefMacro)
    <ImportMany(GetType(IMefMacro))> _
    Private Property Macros() As IEnumerable(Of IMefMacro)
        Get
            Return _Macros
        End Get
        Set(ByVal value As IEnumerable(Of IMefMacro))
            _Macros = value
        End Set
    End Property
    Private Sub RunMacro(ByVal MacroName As String)
        For Each m As IMefMacro In Macros
            If m.Name = MacroName Then
                m.Run(Me, MyContact)
            End If
        Next
    End Sub
 
    Public Interface IMefMacro
        ReadOnly Property Name() As String
        Sub Run(ByVal Application As Object, ByVal Contact As Object)
    End Interface
 
I must be missing something, but I'm not sure what.

Read the full discussion online.

To add a post to this discussion, reply to this email (MEF@discussions.codeplex.com)

To start a new discussion for this project, email MEF@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com

Read the full discussion online.

To add a post to this discussion, reply to this email (MEF@discussions.codeplex.com)

To start a new discussion for this project, email MEF@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com

Jul 31, 2009 at 10:43 PM

Bill, looks like from the snippet you are using inner classes, is that correct?

Glenn

From: BillL [mailto:notifications@codeplex.com]
Sent: Friday, July 31, 2009 12:26 PM
To: Glenn Block
Subject: Re: <ImportMany()> problem [MEF:64122]

From: BillL

Got that, still not working. Here's the corrected code:

MEF Class:

Imports System.ComponentModel.Composition
 
Public Class MEFAddIn
 
    <Export(GetType(IMefMacro))> _
Public Class DoSomethingCoolMacro
        Implements IMefMacro
 
        Public ReadOnly Property Name() As String Implements IMefMacro.Name
            Get
                Return "DoSomethingCoolMacro"
            End Get
        End Property
 
        Public Sub Run(ByVal Application As Object, ByVal parameter As Object) Implements IMefMacro.Run
            MsgBox("Bravo")
        End Sub
    End Class
 
    <Export(GetType(IMefMacro))> _
    Public Class YetAnotherGreatMacro
        Implements IMefMacro
 
        Public ReadOnly Property Name() As String Implements IMefMacro.Name
            Get
                Return "YetAnotherGreatMacro"
            End Get
        End Property
 
        Public Sub Run(ByVal Application As Object, ByVal parameter As Object) Implements IMefMacro.Run
            MsgBox("Tango")
        End Sub
    End Class
 
    Public Interface IMefMacro
        ReadOnly Property Name() As String
        Sub Run(ByVal Application As Object, ByVal Contact As Object)
    End Interface
 
End Class
 
 Main Class:
 
    Public Sub Macro1()
        Compose()
        RunMacro("YetAnotherGreatMacro")
    End Sub
 
    Public Sub Compose()
        Dim Dir As [String] = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments), "ContactManager\Macros\Extensions")
        Dim Catalog As New DirectoryCatalog(Dir)
        Dim Container As New CompositionContainer(Catalog)
        Container.SatisfyImportsOnce(Me)
    End Sub
 
    Private _Macros As IEnumerable(Of IMefMacro)
    <ImportMany(GetType(IMefMacro))> _
    Private Property Macros() As IEnumerable(Of IMefMacro)
        Get
            Return _Macros
        End Get
        Set(ByVal value As IEnumerable(Of IMefMacro))
            _Macros = value
        End Set
    End Property
    Private Sub RunMacro(ByVal MacroName As String)
        For Each m As IMefMacro In Macros
            If m.Name = MacroName Then
                m.Run(Me, MyContact)
            End If
        Next
    End Sub
 
    Public Interface IMefMacro
        ReadOnly Property Name() As String
        Sub Run(ByVal Application As Object, ByVal Contact As Object)
    End Interface
 
I must be missing something, but I'm not sure what.

Read the full discussion online.

To add a post to this discussion, reply to this email (MEF@discussions.codeplex.com)

To start a new discussion for this project, email MEF@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com

Jul 31, 2009 at 11:40 PM

If they are inner classes, this might be the cause as we have a known bug which I have just filed.  The solution would be to not export inner classes.

Glenn

From: gblock [mailto:notifications@codeplex.com]
Sent: Friday, July 31, 2009 2:44 PM
To: Glenn Block
Subject: Re: <ImportMany()> problem [MEF:64122]

From: gblock

Bill, looks like from the snippet you are using inner classes, is that correct?

Glenn

From: BillL [mailto:notifications@codeplex.com]
Sent: Friday, July 31, 2009 12:26 PM
To: Glenn Block
Subject: Re: <ImportMany()> problem [MEF:64122]

From: BillL

Got that, still not working. Here's the corrected code:

MEF Class:

Imports System.ComponentModel.Composition
 
Public Class MEFAddIn
 
    <Export(GetType(IMefMacro))> _
Public Class DoSomethingCoolMacro
        Implements IMefMacro
 
        Public ReadOnly Property Name() As String Implements IMefMacro.Name
            Get
                Return "DoSomethingCoolMacro"
            End Get
        End Property
 
        Public Sub Run(ByVal Application As Object, ByVal parameter As Object) Implements IMefMacro.Run
            MsgBox("Bravo")
        End Sub
    End Class
 
    <Export(GetType(IMefMacro))> _
    Public Class YetAnotherGreatMacro
        Implements IMefMacro
 
        Public ReadOnly Property Name() As String Implements IMefMacro.Name
            Get
                Return "YetAnotherGreatMacro"
            End Get
        End Property
 
        Public Sub Run(ByVal Application As Object, ByVal parameter As Object) Implements IMefMacro.Run
            MsgBox("Tango")
        End Sub
    End Class
 
    Public Interface IMefMacro
        ReadOnly Property Name() As String
        Sub Run(ByVal Application As Object, ByVal Contact As Object)
    End Interface
 
End Class
 
 Main Class:
 
    Public Sub Macro1()
        Compose()
        RunMacro("YetAnotherGreatMacro")
    End Sub
 
    Public Sub Compose()
        Dim Dir As [String] = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments), "ContactManager\Macros\Extensions")
        Dim Catalog As New DirectoryCatalog(Dir)
        Dim Container As New CompositionContainer(Catalog)
        Container.SatisfyImportsOnce(Me)
    End Sub
 
    Private _Macros As IEnumerable(Of IMefMacro)
    <ImportMany(GetType(IMefMacro))> _
    Private Property Macros() As IEnumerable(Of IMefMacro)
        Get
            Return _Macros
        End Get
        Set(ByVal value As IEnumerable(Of IMefMacro))
            _Macros = value
        End Set
    End Property
    Private Sub RunMacro(ByVal MacroName As String)
        For Each m As IMefMacro In Macros
            If m.Name = MacroName Then
                m.Run(Me, MyContact)
            End If
        Next
    End Sub
 
    Public Interface IMefMacro
        ReadOnly Property Name() As String
        Sub Run(ByVal Application As Object, ByVal Contact As Object)
    End Interface
 
I must be missing something, but I'm not sure what.

Read the full discussion online.

To add a post to this discussion, reply to this email (MEF@discussions.codeplex.com)

To start a new discussion for this project, email MEF@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com

Read the full discussion online.

To add a post to this discussion, reply to this email (MEF@discussions.codeplex.com)

To start a new discussion for this project, email MEF@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com

Aug 3, 2009 at 2:23 PM

The Catalog shows 1 Assembly, 1 Loaded File, and 2 Parts.

I took out the enclosing outer class and am still having the same issue.

Aug 3, 2009 at 5:09 PM

Ok - thanks.

I'f found another problem: you seem to be declaring two copies of IMefMacro - one in each assembly.

You'll need to use only a single declaration of IMefMacro (perhaps put it in a third assembly) and then use it from the other two by adding assembly references.

Hope this is it! Fingers crossed...

Nick

Aug 3, 2009 at 7:35 PM

@nblumhardt and gblock

It works now! Thanx for all your help!

Bill