PRISM + MEF - Как указать, какой экспорт использовать? - PullRequest
9 голосов
/ 02 марта 2011

В основном, как я могу указать, какую из моих реализаций выбрать?

FooService.cs

public interface IFooService
{
    Int32 GetFoo();
}

[Export(typeof(IFooService))]
public sealed class Foo100 : IFooService
{
    public Int32 GetFoo()
    {
        return 100;
    }
}


[Export(typeof(IFooService))]
public sealed class Foo200 : IFooService
{
    public Int32 GetFoo()
    {
        return 200;
    }
}

ClientViewModel.cs

[Export()]
public class ClientViewModel : NotificationObject
{
    [Import()]
    private IFooService FooSvc { get; set; }

    public Int32 FooNumber
    {
        get { return FooSvc.GetFoo(); }
    }
}

Boostrapper.cs

public sealed class ClientBootstrapper : MefBootstrapper
{
    protected override void ConfigureAggregateCatalog()
    {
        base.ConfigureAggregateCatalog();

        //Add the executing assembly to the catalog.
        AggregateCatalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
    }

    protected override DependencyObject CreateShell()
    {
        return Container.GetExportedValue<ClientShell>();
    }

    protected override void InitializeShell()
    {
        base.InitializeShell();

        Application.Current.MainWindow = (Window)Shell;
        Application.Current.MainWindow.Show();
    }
}

ClientShell.xaml.cs

[Export()]
public partial class ClientShell : Window
{
    [Import()]
    public ClientViewModel ViewModel
    {
        get
        {
            return DataContext as ClientViewModel;
        }
        private set
        {
            DataContext = value;
        }
    }

    public ClientShell()
    {
        InitializeComponent();
    }
}

Я не уверен, куда идти, чтобы настроить мое приложение для ввода правильного (в этом случае я хочу, чтобы Foo100 был введен. Я знаю, что могу просто позволить им экспортировать как себя и указать вместо него Foo100 IFooService, но это правильный путь?

Ответы [ 3 ]

7 голосов
/ 02 марта 2011

Если имеется несколько экспортов с определенным контрактом, вам придется либо импортировать их все (объявив свойство типа коллекции с атрибутом ImportMany), либо сделать контракты более конкретными, указав название для договора:

[Export("Foo100", typeof(IFooService))]
public sealed class Foo100 : IFooService
{
    public Int32 GetFoo()
    {
        return 100;
    }
}


[Export("Foo200", typeof(IFooService))]
public sealed class Foo200 : IFooService
{
    public Int32 GetFoo()
    {
        return 200;
    }
}

-

[Import("Foo100", typeof(IFooService)]
private IFooService FooSvc { get; set; }
3 голосов
/ 02 марта 2011

Я не думаю, что вы можете указать в MEF, что вы хотите, чтобы импорт синглтона был привязан только к реализации Foo200.

Вы можете либо объявить свойство импорта как IEnumerable, а затем перечислить варианты выбора, чтобы выбрать, какое из них вы хотите использовать в своем собственном коде, или убедиться, что две реализации IFooSvc находятся в разных сборках. и что при определении каталога MEF включается только одна из этих сборок.

1 голос
/ 02 марта 2011

Я не знаком с MEF, поэтому это может быть немного не по назначению, однако, используя Prism и Unity в качестве контейнера DI, вы можете указать ассоциацию с помощью метода RegisterType.Когда у вас есть несколько конкретных типов, реализующих один интерфейс, вы можете связать с ними имя для различия.

IUnityContainer.RegisterType<IFooService, Foo100>("Foo100");
IUnityContainer.RegisterType<IFooService, Foo200>("Foo200");

Затем, когда вы хотите разрешить данный экземпляр, вы можете сделать ...

IUnityContainer.Resolve<IFooService>("Foo200");
...