尝试执行构造函数注入时,Prism + DryIoc崩溃?

时间:2018-09-22 23:41:01

标签: c# xamarin prism dryioc

在使用DryIoc将构造函数注入到Xamarin中的Prism时,我遇到了麻烦。我正在使用Nuget包Prism.DryIoc.Forms。

在我的项目中,我在AuthenticatePage.xaml.g.cs中得到以下错误

Unable to resolve Object {RequiredServiceType=Project.ViewModels.AuthenticatePageViewModel} with 1 arg(s) 
in wrapper Func<Xamarin.Forms.Page, Object> {RequiredServiceType=Project.ViewModels.AuthenticatePageViewModel} with 1 arg(s) 
from container
with normal and dynamic registrations:
MainPage, {ID=44, ImplType=Project.Views.MainPage}}
NavigationPage, {ID=43, ImplType=Xamarin.Forms.NavigationPage}}
AuthenticatePage, {ID=45, ImplType=Project.Views.AuthenticatePage}}

具体来说,它指向直线

private void InitializeComponent() {
        global::Xamarin.Forms.Xaml.Extensions.LoadFromXaml(this, typeof(AuthenticatePage));
    }

值得注意的是,如果我在App.OnInitialized中调用以下内容,则该对象可以很好地解析:

c.Register<INegotiator, Negotiator>(Reuse.Singleton);
var n = c.Resolve<INegotiator>();
n.ResumeSessionAsync(); // This works fine, no problems.
await NavigationService.NavigateAsync("NavigationPage/AuthenticatePage"); // Error thrown here

如果我从ViewModel中删除了构造函数注入,则可以正常工作(除了保留默认的navigationService注入之外,它仍然可以正常运行)。甚至尝试注入像ILogger这样的基本类(无依赖项)都失败。

public AuthenticatePageViewModel(INavigationService navigationService, ILogger logger) : base (navigationService)
{
    Title = "Authentication Page...";
}

我将继续调查,但是如果我从根本上做错了什么,这对这里的人是否显而易见?如果我不得不猜测,那是与与内置在Ioc容器和DryIoc中的棱镜的冲突有关吗?

编辑:

我正在使用NuGet(7.0.0.396)上提供的最新版本的Prism.DryIoc.Forms,其中包括DryIoc 2.12.26。到目前为止,我只是简单地遵循可用于Visual Studio的模板,该模板列出了如下设置导航:

protected override async void OnInitialized()
{
    InitializeComponent();

    var c = new Container();
    c.Register<ILogger, LoggerConsole>(Reuse.Singleton);

    c.RegisterMany(new[] { Assembly.Load("Project.UWP") },
                   serviceTypeCondition: type => type == typeof (ILocalFileHandler));

    c.Register<INegotiator, Negotiator>(Reuse.Singleton);
    // var n = c.Resolve<INegotiator>(); 
    // n.ResumeSessionAsync(); // <- This will run fine. Negotiator class has ILogger and ILocalFileHandler injected into it.

    await NavigationService.NavigateAsync("NavigationPage/AuthenticatePage");

}

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
    containerRegistry.RegisterForNavigation<NavigationPage>();
    containerRegistry.RegisterForNavigation<MainPage>();
    containerRegistry.RegisterForNavigation<AuthenticatePage>();
}

在网上是否可以找到有关是否应该/如何使用Prism.DryIoc.DryIocContainerExtensions来设置导航的任何信息?即使修改示例应用程序以包含基本构造注入,也会在同一xaml.g.cs文件中导致错误“值不能为空”?

2 个答案:

答案 0 :(得分:1)

Prism 7.0和更低版本允许异常冒出,为了诊断问题的根本原因,您希望更好地诊断此问题,我建议您进行一些尝试/捕获,以查看错误的真正原因和位置。

protected override void OnInitialized()
{
    try
    {
        // Check if there is an initialization exception
        var page = new AuthenticationPage();

        // Validate that the page resolves ok
        var page2 = Container.Resolve<object>("AuthenticationPage");

        // Validate that your ILogger interface is registered and resolves ok
        var logger = Container.Resolve<ILogger>();

        // Check for Registration/initialization exceptions
        var vm = Container.Resolve<AuthenticationPageViewModel>();
    }
    catch(Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(ex);
        System.Diagnostics.Debugger.Break();
    }
}

您尚未指定收到此错误的时间,尽管通常启用XAML编译后,您会在编译过程中看到{pageName}.xaml.g.cs中的异常,而不是运行时。无论哪种方式,鉴于您的异常都来自于类背后生成的XAML代码,因此这告诉我,您的XAML最有可能是问题。验证此问题的一种非常简单的方法是删除AuthenticationPage中的所有XAML内容,以便您拥有一个空白页面。

考虑到作为问题一部分提供的代码,我想说您没有为ILogger接口注册,这很可能会引发异常,从而导致您遇到的问题。无论错误在哪里/在哪里,上面显示的try / catch都是确定根本原因的最简单方法。

答案 1 :(得分:1)

按照@Dan S.的诊断建议并阅读本文(http://brianlagunas.com/whats-new-in-prism-for-xamarin-forms-7-0/),我意识到我应该一直在使用Prism.Ioc.ContainerRegistry抽象层与DryIoc交互。在此之前,我曾直接与DryIoc的班级合作。

一旦我修改了注册码以使用Prism.Ioc.IContainerRegistry,它就可以正常工作。

protected override void RegisterTypes(IContainerRegistry cr)
{
    cr.Register<ILogger, LoggerConsole>();

    cr.GetContainer().RegisterMany(new[] { Assembly.Load("Project.UWP") },
                   serviceTypeCondition: type => type == typeof(ILocalFileHandler));

    cr.Register<INegotiator, Negotiator>();


    cr.RegisterForNavigation<NavigationPage>();
    cr.RegisterForNavigation<MainPage>();
    cr.RegisterForNavigation<AuthenticatePage>();
}