PRISM + MEF - 如何指定要使用的导出?

时间:2011-03-01 21:04:55

标签: c# dependency-injection service prism mef

基本上,我如何指定可供选择的实现?

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 个答案:

答案 0 :(得分:7)

如果某个合同中有多个导出,那么您必须全部导入它们(通过声明其上带有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; }

答案 1 :(得分:3)

我认为您不能在MEF中指定您希望单独导入仅限于Foo200实现。

您可以将您的import属性声明为IEnumerable,然后您可以枚举选择以选择您要在自己的代码中使用哪一个,或者您可以确保IFooSvc的两个实现位于不同的程序集中并且在定义MEF目录时只包含其中一个程序集。

答案 2 :(得分:1)

我不熟悉MEF所以这可能稍微偏离基础,但是使用Prism和Unity作为DI容器,您可以通过RegisterType方法指定关联。当您有多个具体类型实现单个接口时,您可以将名称与它们相关联以进行区分。

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

然后,当你想解决给定的实例时,你可以做...

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