Создать экземпляр Singleton в MEF2 - PullRequest
0 голосов
/ 29 августа 2018

Я создаю приложение с несколькими плагинами, используя MEF2 (Microsoft.Composition). Эти плагины должны импортировать некоторый общий объект, и все они должны использовать один и тот же экземпляр этого объекта ... так что это типичный Singleton.

Однако, когда я [Import] добавляю этот общий объект в мои плагины, все они получают свою собственную копию вместо общей.

В .NET Framework MEF1 все объекты были созданы как одиночные по умолчанию. Похоже, что это не относится к .NET Core MEF2.

Как я могу убедиться, что все мои плагины получают один и тот же экземпляр моего общего объекта?

Пример кода

Запуск

static void Main(string[] args) {
    ContainerConfiguration containerConfig = new ContainerConfiguration()
        .WithAssembly(Assembly.GetExecutingAssembly())
        .WithAssembly(typeof(ICommonObject).Assembly);

    using (CompositionHost container = containerConfig.CreateContainer())             {
        _mainApp = container.GetExport<MainApp>();
        _mainApp.Start();
    }
}

MainApp

[Export(typeof(MainApp))]
public class MainApp {
    [Import] public ICommonObject CommonObject { get; set; }
    [ImportMany] public IEnumerable<IPlugin> Plugins { get; set; }

    public void Start() {
        CommonObject.SomeValue = "foo";
        Console.WriteLine("SomeValue (from MainApp): " + CommonObject.SomeValue);

        foreach (IPlugin plugin in Plugins) {
            plugin.Start();
        }
    }
}

Plugin

[Export(typeof(IPlugin))]
public class SomePlugin : IPlugin {

    [Import] public ICommonObject CommonObject { get; set; }

    public void Start() {
        Console.WriteLine("SomeValue (from plugin): " + CommonObject.SomeValue);
    }
}

выход

SomeValue (from MainApp): foo
SomeValue (from plugin):

1 Ответ

0 голосов
/ 30 августа 2018

После долгих проб и ошибок я, кажется, наконец-то сам нашел решение.

Трюк, похоже, заключается в использовании ConventionBuilder. У него есть метод расширения под названием .Shared(), который превращает все объекты, полученные из определенного типа, в синглтон.

Для моих примеров кода просто добавьте следующее в начало кода запуска:

ConventionBuilder conventions = new ConventionBuilder();
conventions.ForTypesDerivedFrom<ICommonObject>()
    .Export<ICommonObject>()
    .Shared();

ContainerConfiguration containerConfig = new ContainerConfiguration()
    .WithAssembly(Assembly.GetExecutingAssembly(), conventions);

По какой-то причине объект, реализующий ICommonObject, даже не нуждается в атрибуте [Export]. В любом случае вывод из примера теперь:

SomeValue (from MainApp): foo
SomeValue (from plugin): foo
...