Вызывается только конструктор по умолчанию

Я пытаюсь передать службу конструктору компонентов в MAUI:

public partial class MyComponent: ContentView
{
    public MyComponent(MyService service)
    {
        InitializeComponent();

        data = service.getData();
    }
}

Но он выдает ошибку и просит добавить конструктор по умолчанию:

public partial class MyComponent: ContentView
{

    public MyComponent() { }

    public MyComponent(MyService service)
    {
        InitializeComponent();

        data = service.getData();

    }
}

Я добавил синглтоны, чтобы передать службу компоненту:

builder.Services.AddSingleton<MyComponent>();
builder.Services.AddSingleton<MyService>();

Я также пробовал этот метод:

builder.Services.AddSingleton(sp => new MyComponent(sp.GetService<MyService>()));

Ни один из них не работал. Вызывается только конструктор по умолчанию

Я использую компонент на странице следующим образом:

<ContentPage ...
             xmlns:components = "clr-namespace:MyApp.Components">
        <components:MyComponent/>
</ContentPage>

Как передать службу компоненту?

Laravel с Turbo JS
Laravel с Turbo JS
Turbo - это библиотека JavaScript для упрощения создания быстрых и высокоинтерактивных веб-приложений. Она работает с помощью техники под названием...
Типы ввода HTML: Лучшие практики и советы
Типы ввода HTML: Лучшие практики и советы
HTML, или HyperText Markup Language , является стандартным языком разметки, используемым для создания веб-страниц. Типы ввода HTML - это различные...
Аутсорсинг разработки PHP для индивидуальных веб-решений
Аутсорсинг разработки PHP для индивидуальных веб-решений
Услуги PHP-разработки могут быть экономически эффективным решением для компаний, которые ищут высококачественные услуги веб-разработки по доступным...
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
Слишком много useState? Давайте useReducer!
Слишком много useState? Давайте useReducer!
Современный фронтенд похож на старую добрую веб-разработку, но с одной загвоздкой: страница в браузере так же сложна, как и бэкенд.
Узнайте, как использовать теги &lt;ul&gt; и &lt;li&gt; для создания неупорядоченных списков в HTML
Узнайте, как использовать теги <ul> и <li> для создания неупорядоченных списков в HTML
HTML предоставляет множество тегов для структурирования и организации содержимого веб-страницы. Одним из наиболее часто используемых тегов для...
0
0
72
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы не могли напрямую использовать внедрение зависимостей в настраиваемый элемент управления.

См. этот выпуск на Github: Внедрение зависимостей для пользовательских элементов управления. Это все еще находится на рассмотрении, и вы можете следить за этой проблемой.

Должны быть какие-то обходные пути. Так же, как комментарий tripjump в предыдущем выпуске, вы можете прикрепить связываемое свойство и внедрить viewModel из MainPage через это свойство. Я только что сделал небольшую демонстрацию для вас.

Для управления MyComponent:

public partial class MyComponent : ContentView
{

    public static readonly BindableProperty ServiceProperty = BindableProperty.Create(nameof(Service),typeof(MyService), typeof(MyComponent),propertyChanged: OnServiceChanged);

    static void OnServiceChanged(BindableObject bindable, object oldValue, object newValue)
    {
    // Property changed implementation goes here
        MyService a = newValue as MyService;
    }

    public MyService Service
    {
        get => (MyService)GetValue(MyComponent.ServiceProperty);
        set => SetValue(MyComponent.ServiceProperty, value);
    }

    public MyComponent()
    {
        InitializeComponent();
    }
}

Для MainPage, которая использует MyComponent:

<ContentPage xmlns = "http://schemas.microsoft.com/dotnet/2021/maui"
         ...
         x:Name = "this">

<components:MyComponent BindingContext = "{x:Reference this}" MyService = "{Binding BindingContext.service}"/>

Для MainPageViewModel, которая является BindingContext для MainPage:

public class MainPageViewModel
{
    public MyService service { get; set; }

    public MainPageViewModel(MyService myService)
    {
        service = myService;
    }
}

А также добавить сервис в MauiProgram:

    builder.Services.AddSingleton<MainPage>();
    builder.Services.AddSingleton<MainPageViewModel>();
    builder.Services.AddSingleton<MyService>();

Надеюсь, это сработает для вас.

Ответ принят как подходящий

Вы также можете использовать внедрение зависимостей, как в там.

Создайте класс ServiceProvider:

public static class ServiceProvider
{
    public static TService GetService<TService>()
        => Current.GetService<TService>();

    public static IServiceProvider Current
        =>
#if WINDOWS10_0_17763_0_OR_GREATER
            MauiWinUIApplication.Current.Services;
#elif ANDROID
            MauiApplication.Current.Services;
#elif IOS || MACCATALYST
            MauiUIApplicationDelegate.Current.Services;
#else
            null;
#endif
}

Затем вы можете просто использовать его в любом конструкторе компонентов:

_Contexte = ServiceHelper.GetService<Contexte>();

Что касается того, почему вы не можете передать параметр компонентам XAML, это потому, что они преобразуются в код C#, а затем автоматически обрабатываются. Если у конструктора есть аргумент, механизм, обрабатывающий преобразование, не будет знать, какой экземпляр передать конструктору (если только Microsoft не решит обработать DI, что может произойти в какой-то момент).

Другие вопросы по теме

Похожие вопросы

Как заставить объект вращаться вокруг цели со случайной высотой и с возможностью изменения радиуса вращения?
Как настроить среду хостинга для конкретного сайта?
Использование LinQ для доступа к нескольким таблицам. Каков правильный способ объединения этих таблиц с помощью LinQ, чтобы они были такими же, как SQL Query?
Что такое эквивалент System.Text.Json для XmlElment (имя, тип)
С помощью объекта десериализации newtonsoft json, содержащего массив/список, с использованием словаря
Группировка списка Мауи
Winforms ListBox с DataSource, привязанным к пунктирному пути вложенного объекта, дает сбой, когда промежуточный объект пунктирного пути имеет значение null
.NET Core 6: для защиты потенциально конфиденциальной информации в строке подключения.
Как автоматически вызвать конструктор по имени типа без отражения в С#?
Как я могу добавить базовый конструктор в класс подключения к базе данных?