Importing into a Exported object with MEF
I'm sorry if this question has already been asked 100 times, but I'm really struggling to get it to work.
Say I have have three projects.
- Core.dll
- Has common interfaces
- Shell.exe
- Loads all modules in assembly folder.
- References Core.dll
- ModuleA.dll
- Exports Name, Version of module.
- References Core.dll
Shell.exe has a [Export] that contains an single instance of a third party application that I need to inject into all loaded modules.
So far the code that I have in Shell.exe is:
static void Main(string[] args)
{
ThirdPartyApp map = new ThirdPartyApp();
var ad = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var dircatalog = new DirectoryCatalog(".");
var a = new AggregateCatalog(dircatalog, ad);
// Not to sure what to do here.
}
class Test
{
[Export(typeof(ThirdPartyApp))]
public ThirdPartyApp Instance { get; set; }
[Import(typeof(IModule))]
public IModule Module { get; set; }
}
I need to create a instance of Test, and load Instance
with map
from the Main
method then load the Module from ModuleA.dll that is in the executing directory then [Import] Instance
into the loaded module.
In ModuleA
I have a class like this:
[Export(IModule)]
class Module : IModule
{
[Import(ThirdPart开发者_运维技巧yApp)]
public ThirdPartyApp Instance {get;set;}
}
I know I'm half way there I just don't know how to put it all together, mainly with loading up test with a instance of map
from Main
.
Could anyone help me with this.
I seem to be able to get it to work this way, in the constructor of the Test class(yes I know not to do work in the constructor, I will move it out):
public Test()
{
ThirdPartyApp map = new ThirdPartyApp();
this.MapInfoInstance = map;
//What directory to look for!
String strPath = AssemblyDirectory;
using (var Catalog = new AggregateCatalog())
{
DirectoryCatalog directorywatcher = new DirectoryCatalog(strPath, "*.dll");
Catalog.Catalogs.Add(directorywatcher);
CompositionBatch batch = new CompositionBatch();
batch.AddPart(this);
CompositionContainer container = new CompositionContainer(Catalog);
//get all the exports and load them into the appropriate list tagged with the importmany
container.Compose(batch);
foreach (var part in Catalog.Parts)
{
container.SatisfyImportsOnce(part);
}
}
Module.Run();
}
Your main method should probably look like this:
static void Main(string[] args)
{
var exeCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var dircatalog = new DirectoryCatalog(".");
var aggregateCatalog = new AggregateCatalog(exeCatalog, dirCatalog);
var container = new CompositionContainer(aggregateCatalog);
var program = container.GetExportedValue<Program>();
program.Run();
}
To make an instance of the ThirdPartyApp
class available as a part that can be imported by your modules, you have two options. The first is to explicitly add such an instance to the container with the ComposeExportedValue
extension method like this:
container.ComposeExportedValue<ThirdPartyApp>(new ThirdPartyApp());
Alternatively, you can export it via a property by having a class like this one:
public class ThirdPartyAppExporter
{
private readonly ThirdPartyApp thirdPartyApp = new ThirdPartyApp();
[Export]
public ThirdPartyApp ThirdPartyApp { get { return thirdPartyApp; } }
}
精彩评论