Я пытаюсь передать службу конструктору компонентов в 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>
Как передать службу компоненту?
Вы не могли напрямую использовать внедрение зависимостей в настраиваемый элемент управления.
См. этот выпуск на 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, что может произойти в какой-то момент).