问题
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?
回答1:
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 )
回答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 );
来源:https://stackoverflow.com/questions/21313016/using-mef-with-abstract-base-class