Binding to a MEF ExportCollection

Josh said this in the MEF discussion list on CodePlex:

MEF is just a composition engine its job isn’t really to offer choices for a users.

While that is true, it’s not that hard to present choices to users and it gives you a bit of insight into the very powerful strongly typed metadata attributes of MEF.

MEF is a tool for matching up parts. Its discoverability is not against the actual class, because that would require too deep a dive into the assembly. Its discoverability is based on class attributes which announce that a part fulfills a contract. In MEF, a contract ID is always a string and you’re committing to fulfill expectations someone will have about something that claims that contract. I almost always use one of two types of contracts – type contracts against interfaces that formalize my commitments and simple strings when I have a random piece of information floating around like a database or server name. To clarify how it works, MEF turns the type into a string for its internal use.  

When you create an interface for MEF you have the option to create metadata to use with it. Metadata generally (always in my case) exists as two pieces – an attribute and an interface. What happens internally is that MEF creates a dictionary with the data provided by the attribute. At runtime, you can request that you only see parts that fulfill the contract and metadata by supplying contract interface and metadata interface. If you strongly type this via the generic overload you have a MetadataView property which is of the type of your metadata interface.

You can explore this more in the documentation for strongly typed attributes at the MEF site on CodePlex.

From a binding perspective, if you want to bind something you create an ExportCollection(Of IFoo, IFooMetadata). This is a collection of export objects which have a IFooMetadata strongly typed MetadataView property. With me so far?

   <Import()> _

   Private mDatabaseServices As _

ExportCollection(Of IDatabaseServices, _

IDatabaseServicesComposition)

 

And in the Load method:

      providerComboBox.ItemsSource = mDatabaseServices

 

You can bind to this export collection (FriendlyName is a property on my metadata interface):

     <ComboBox Grid.Row=”1″ Grid.Column=”1″ Name=”providerComboBox”

                SelectionChanged=”providerComboBox_SelectionChanged”>

         <ComboBox.ItemTemplate>

            <DataTemplate>

               <TextBlock Text=”{Binding Path=MetadataView.FriendlyName}”/>

            </DataTemplate>

         </ComboBox.ItemTemplate>

      </ComboBox>

 

ExportCollection is not an ObservableCollection, so if you want those extra features, you can create one yourself.  In the Load method this is simply:

      availableOutputs.ItemsSource = OutputItem.GetBindableList(mOutputListeners)

 

where OutputItem is

Public Class OutputItem

   Private mExport As Export(Of IOutputListener, IOutputListenerComposition)

 

   Public Shared Function GetBindableList( _

               ByVal list As IEnumerable(Of Export(Of IOutputListener, IOutputListenerComposition))) _

               As ObservableCollection(Of OutputItem)

      Dim ret = New ObservableCollection(Of OutputItem)

      For Each item In list

         ret.Add(New OutputItem(item))

      Next

      Return ret

   End Function

 

   Private Sub New(ByVal export As Export(Of IOutputListener, IOutputListenerComposition))

      mExport = export

   End Sub

 

    Public ReadOnly Property FriendlyName() As String

      Get

         Return mExport.MetadataView.FriendlyName

      End Get

   End Property

 

The XAML for binding this is:

      <ListBox Grid.Row=”5″ Grid.Column=”1″ Name=”availableOutputs” >

         <ListBox.ItemTemplate>

            <DataTemplate>

               <CheckBox  Content=”{Binding Path=FriendlyName}”

                           IsChecked=”{Binding Path=IsActive}” />

            </DataTemplate>

         </ListBox.ItemTemplate>

      </ListBox>

 

Where differences other than in the binding are because I’m solving a different problem.

 

One thought on “Binding to a MEF ExportCollection”

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>