Unity/Caliburn Micro,具有多个参数的注入构造函数

发布于 2024-11-18 11:54:34 字数 1830 浏览 6 评论 0原文

我目前正在尝试学习如何使用 Unity 和 Caliburn Micro 实现 MVVM。在其他地方寻求帮助后,我仍然不确定如何正确设置构造函数注入。我不知道这是否行不通,因为我缺乏 MVVM 或其他方面的专业知识。

我的问题是我想将两个 IScreen 对象传递到我的主窗口(shell)类中,当用户单击按钮时可以在它们之间导航。这是我的 MainWindowViewModel 类中的构造函数的代码:

private IScreen campaignViewModel, stringsViewModel;
public MainWindowViewModel(IScreen campaignViewModel, IScreen stringsViewModel)
{
    this.campaignViewModel = campaignViewModel;
    this.stringsViewModel = stringsViewModel;
    ActiveItem = this.campaignViewModel;
}

这是我在 Bootstrapper(Unity) 类中使用的代码:

    private static IUnityContainer BuildContainer()
    {
        IUnityContainer result = new UnityContainer();
        result
            .RegisterInstance(result)
            .RegisterInstance<IWindowManager>(new WindowManager())
            .RegisterInstance<IEventAggregator>(new EventAggregator());

        result
            .RegisterType<IScreen, CampaignsViewModel>()
            .RegisterType<IScreen, StringsViewModel>()
            .RegisterType<MainWindowViewModel>(new InjectionConstructor(typeof(IScreen), typeof(IScreen)));

        return result;
    }

    protected override object GetInstance(Type service, string key)
    {
        var result = unity.Resolve(service, key);

        if (result == null)
            throw new Exception(string.Format("Could not locate any instance of contract {0}", service));
        return result;
    }

运行时,MainWindowViewModel 接收 StringsViewModel 的两个实例。尽管如果我将一个键放入语句中:

result.RegisterType<IScreen, StringsViewModel>("StringsView");

然后它会传入 CampaignsViewModel 的两个实例。我不知道如何向 InjectionConstructor 指定我希望它传入 CampaignViewModel 和 StringsViewModel 的一个实例。我有一种感觉,这可能与 GetInstance 方法有关,但我不确定。

任何帮助将不胜感激!

谢谢。

I am currently trying to learn how to implement MVVM using Unity and Caliburn Micro. After looking around for help elsewhere I am still unsure about how to set up the Constructor Injection properly. I don't know if this is not working due to my lack of expertise in MVVM or something else.

My problem is I want to pass in two IScreen Objects into my main window(shell) Class that can be navigated between when the user clicks on a button. Here is the code for the constructor in my MainWindowViewModel class:

private IScreen campaignViewModel, stringsViewModel;
public MainWindowViewModel(IScreen campaignViewModel, IScreen stringsViewModel)
{
    this.campaignViewModel = campaignViewModel;
    this.stringsViewModel = stringsViewModel;
    ActiveItem = this.campaignViewModel;
}

This is the code I am using in my Bootstrapper(Unity) class:

    private static IUnityContainer BuildContainer()
    {
        IUnityContainer result = new UnityContainer();
        result
            .RegisterInstance(result)
            .RegisterInstance<IWindowManager>(new WindowManager())
            .RegisterInstance<IEventAggregator>(new EventAggregator());

        result
            .RegisterType<IScreen, CampaignsViewModel>()
            .RegisterType<IScreen, StringsViewModel>()
            .RegisterType<MainWindowViewModel>(new InjectionConstructor(typeof(IScreen), typeof(IScreen)));

        return result;
    }

    protected override object GetInstance(Type service, string key)
    {
        var result = unity.Resolve(service, key);

        if (result == null)
            throw new Exception(string.Format("Could not locate any instance of contract {0}", service));
        return result;
    }

When this runs the MainWindowViewModel receives two instances of StringsViewModel. Although if I were to put a key into the statement:

result.RegisterType<IScreen, StringsViewModel>("StringsView");

Then it passes in two instances of CampaignsViewModel. I don't know how to specify to the InjectionConstructor that I want it to pass in one instance of CampaignViewModel and StringsViewModel. I have a feeling it may have something to do with the GetInstance method, but I am unsure.

Any help would be greatly appreciated!

Thanks.

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

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

发布评论

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

评论(2

小糖芽 2024-11-25 11:54:34

在构造函数中,您定义相同的接口两次。

DI 框架如何知道哪个是哪个?答:不可以。

因此,不要使用 2 个接口:

 public MainWindowViewModel(ICampaignScreen campaignViewModel, IStringsScreen stringsViewModel)

您可以使这两个接口都继承自 IScreen:

 public interface ICampaignScreen : IScreen

并且不需要向 IScreen 添加任何内容 - 它们只是为框架提供了一种区分它们的方法。

In your constructor you define the same interface twice.

How will the DI framework know which is which?? Answer: it can't.

So instead of this use 2 interfaces:

 public MainWindowViewModel(ICampaignScreen campaignViewModel, IStringsScreen stringsViewModel)

You can make both of these inherit from IScreen:

 public interface ICampaignScreen : IScreen

and neither need add anything to IScreen - they simply provide a means for the Framework to differentiate between them.

云淡月浅 2024-11-25 11:54:34

更改为:

 result
            .RegisterType<IScreen, CampaignsViewModel>()
            .RegisterType<IScreen, StringsViewModel>()
            .RegisterType<MainWindowViewModel>(new InjectionConstructor(typeof(IScreen), typeof(IScreen)));

至:

 result
            .RegisterType<IScreen, CampaignsViewModel>()
            .RegisterType<IScreen, StringsViewModel>()
            .RegisterType<MainWindowViewModel>(new InjectionConstructor(typeof(CampaignsViewModel), typeof(StringsViewModel)));

这有效。我不知道它是否违反任何规则或原则,但它目前有效。

Changed:

 result
            .RegisterType<IScreen, CampaignsViewModel>()
            .RegisterType<IScreen, StringsViewModel>()
            .RegisterType<MainWindowViewModel>(new InjectionConstructor(typeof(IScreen), typeof(IScreen)));

To:

 result
            .RegisterType<IScreen, CampaignsViewModel>()
            .RegisterType<IScreen, StringsViewModel>()
            .RegisterType<MainWindowViewModel>(new InjectionConstructor(typeof(CampaignsViewModel), typeof(StringsViewModel)));

And this worked. I don't know if it violates any rules or principles but it works for now.

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