Импорт в экспортируемый объект с помощью MEF - PullRequest
0 голосов
/ 10 июня 2010

Извините, если этот вопрос уже задавался 100 раз, но я действительно изо всех сил пытаюсь заставить его работать.

Скажем, у меня есть три проекта.

  • Core.dll
    • Имеет общие интерфейсы
  • Shell.exe
    • Загружает все модули в папке сборки.
    • Ссылки Core.dll
  • ModuleA.dll
    • Имя экспорта, версия модуля.
    • Ссылки Core.dll

Shell.exe имеет [Export], который содержит один экземпляр стороннего приложения, который мне нужно внедрить во все загруженные модули.

Пока что код, который у меня есть в Shell.exe:

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; }
}

Мне нужно создать экземпляр Test и загрузить Instance с map из метода Main, затем загрузить модуль из ModuleA.dll, который находится в каталоге выполнения, затем [Import] Instance в загруженный модуль.

В ModuleA У меня есть такой класс:

[Export(IModule)]
class Module : IModule
{
    [Import(ThirdPartyApp)]
    public ThirdPartyApp Instance {get;set;}
}

Я знаю, что я на полпути, я просто не знаю, как все это собрать, в основном с загрузкой теста с экземпляром map из Main.

Может ли кто-нибудь помочь мне с этим.

Ответы [ 2 ]

0 голосов
/ 10 июня 2010

Ваш основной метод, вероятно, должен выглядеть следующим образом:

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();
}

Чтобы сделать экземпляр класса ThirdPartyApp доступным как деталь, которая может быть импортирована вашими модулями, у вас есть два варианта. Первый заключается в явном добавлении такого экземпляра в контейнер с помощью метода расширения ComposeExportedValue, например:

container.ComposeExportedValue<ThirdPartyApp>(new ThirdPartyApp());

Кроме того, вы можете экспортировать его через свойство, используя такой класс:

public class ThirdPartyAppExporter
{
    private readonly ThirdPartyApp thirdPartyApp = new ThirdPartyApp();

    [Export]
    public ThirdPartyApp ThirdPartyApp { get { return thirdPartyApp; } }
}
0 голосов
/ 10 июня 2010

Кажется, я могу заставить его работать таким образом в конструкторе класса Test (да, я знаю, что не нужно работать в конструкторе, я его переместу):

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();
    }
...