棱镜MEF——如何指定使用哪个导出?

发布于 2024-10-20 05:38:01 字数 1898 浏览 5 评论 0原文

基本上,我如何指定要选择哪些实现?

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 ,但那是吗?正确的方法是什么?

Basically, how can I specify which of my implementations to choose from?

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

I'm not sure where to go from here for setting up my app to inject the correct one (in this case, I want Foo100 to be injected. I know I can just let them export as themselves and specify a Foo100 instead of an IFooService, but is that the correct way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

紫瑟鸿黎 2024-10-27 05:38:01

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

If there are more than one exports with a certain contract then you will have to either import them all (by declaring a property of a collection type with the ImportMany attribute on it) or make the contracts more specific by specifying a name for the contract:

[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; }
若水微香 2024-10-27 05:38:01

我认为您不能在 MEF 中指定您希望单例导入仅绑定到 Foo200 实现。

您可以将导入属性声明为 IEnumerable,然后可以通过选择进行枚举以选出要在自己的代码中使用的属性,或者您可以确保 IFooSvc 的两个实现驻留在不同的程序集中,并且仅当您定义 MEF 目录时,会包含这些程序集之一。

I don't think you can specify in MEF that you want your singleton import bound only to the Foo200 implementation.

You can either declare your import property as an IEnumerable and then you can enumerate through the selections to pick out which one you want to use in your own code, or you can make sure that the two implementations of IFooSvc reside in different assemblies and that only one of those assemblies is included when you're defining your MEF catalog.

極樂鬼 2024-10-27 05:38:01

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

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

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

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

I'm not familiar with MEF so this may be slightly off base however using Prism and Unity as the DI container you can specify the association via the RegisterType method. When you have multiple concrete types implementing the single interface you can associate a name with them for distinction.

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

Then when you want to resolve the given instance you can do...

IUnityContainer.Resolve<IFooService>("Foo200");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文