Question

I'm building a database import app than I want to be extensible (custom db models can be added as needed). My base component has methods that extended types have to implement: MapData & SaveData.

I defined the base as an abstract class, and everything works when the extended types are in the same namespace. However, I want to use MEF to import extended types in a different namespace at runtime, but I can't figure out how to do that.

Base class:

namespace Program
{
   public abstract class Component
   {
      public abstract string TypeName { get; }
      public abstract DataSet MapData( DataSet db );
      public abstract bool SaveData();
   }
}

Extended class (in a separate project):

using Program.Component;
namespace ExtendedType
{
   [Export( typeof( Component )]
   class Type1 : Component
   {
       public override string TypeName { get { return "Type1" } }
       public override DataSet MapData( DataSet db )
       {
          // create various object models from db here 
          return db;
       }
       public override bool SaveData()
       {
          // save object models 
          return true;
       }
   }
}

Program to import all extended types:

namespace Program
{
   [ImportMany( typeof( Component ) )]
   public IEnumerable<Component> componentTypes;

   public Program()
   {
        var catalog = new AggregateCatalog();
        catalog.Catalogs.Add( new AssemblyCatalog( typeof( Component ).Assembly ) );
        container = new CompositionContainer( catalog );
        this.container.ComposeParts( this );
   }
}

According to what I've read, the [ImportMany] attribute on IEnumerable should fill that at runtime but it's always empty. The CompositionContainer is always empty as well.

What did I set up incorrectly? How can I get a list of the extended Component types?

Was it helpful?

Solution 2

I ended up creating an Extensions directory for the MEF components to live in and setting a variable in App.Config as well as the Build directory of the other projects to point there. Thanks to @JaredPar for the help.

 var extensionFolder = ConfigurationManager.AppSettings["ExtensionPath"];
 var solutionPath = Directory.GetParent( System.IO.Directory.GetCurrentDirectory() ).Parent.FullName;
 var catalog = new AggregateCatalog();
 catalog.Catalogs.Add( new DirectoryCatalog( solutionPath + extensionFolder ) );
 var container = new CompositionContainer( catalog );
 container.ComposeParts( this );

OTHER TIPS

MEF will only search the set of types / assemblies that is defined by the CompositionContainer. In this case the assembly for Type1 isn't in there hence it's never found. In order or this to work you need to include the assembly for Type1 in the CompositionContainer as well.

 catalog.Catalogs.Add( new AssemblyCatalog( typeof( Type1 ).Assembly )
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top