Prism + DryIoc дает сбой при попытке выполнить инжекцию в конструктор? - PullRequest
0 голосов
/ 23 сентября 2018

У меня проблемы с использованием DryIoc для внедрения конструктора в ViewModel с использованием Prism с Xamarin.Я использую пакет 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, она работает нормально (Помимо сохранения внедрения по умолчанию навигационной службы, которая работает нормально).Даже попытка внедрить базовый класс, такой как ILogger (без зависимостей), терпит неудачу.

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

Я собираюсь продолжить расследование, но для кого-то здесь очевидно, что я в принципе делаю что-то не так?Если бы мне пришлось угадывать, я бы сказал, что это связано с конфликтом призм, встроенных в контейнер Ioc и DryIoc?

Редактировать:

Я использую последнюю версиюPrism.DryIoc.Forms доступны на NuGet (7.0.0.396), который говорит, что включает 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 голосов
/ 24 сентября 2018

Следуя предложению @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>();
}
0 голосов
/ 24 сентября 2018

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.Очень простой способ проверить это - удалить все содержимое XAML с вашей страницы аутентификации, чтобы у вас была пустая страница.

Учитывая код, который вы указали как часть вашего вопроса, я бы сказал, что у вас нет регистрации для вашего интерфейса ILogger, что, вероятно, приведет к исключению, вызывающему возникшую проблему.Независимо от того, в чем / где ошибка, показанный выше пример попытки / отловки будет самым простым способом определить основную причину.

...