2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Cet article utilise le projet WPF Gallery pour découvrir les concepts associés à l'injection de dépendances et comment effectuer l'injection de dépendances dans WPF.
L'injection de dépendances (DI) est un modèle de conception utilisé pour mettre en œuvre le principe d'inversion de contrôle (IoC). L'objectif principal de l'injection de dépendances est de transférer la création d'objets et la gestion des dépendances entre objets depuis l'intérieur de l'objet vers un conteneur ou un framework externe, améliorant ainsi la maintenabilité, la testabilité et la flexibilité du code.
Le concept de base de l’injection de dépendances
Types d'injection de dépendances
injection constructeur: L'objet dépendant est passé via le constructeur de la classe.
public class OrderService
{
private readonly IProductRepository _productRepository;
public OrderService(IProductRepository productRepository)
{
_productRepository = productRepository;
}
}
Injection de propriété: Les objets dépendants sont transmis via les propriétés publiques de la classe.
public class OrderService
{
public IProductRepository ProductRepository { get; set; }
}
méthode d'injection: L'objet dépendant est passé via le paramètre méthode de la classe.
public class OrderService
{
public void ProcessOrder(IProductRepository productRepository)
{
// 使用 productRepository 处理订单
}
}
L'injection de dépendances (DI) est un modèle de conception grâce auquel la création d'objets et la gestion des dépendances entre objets peuvent être transférées de l'intérieur de l'objet vers un conteneur ou un framework externe. Il existe plusieurs raisons et avantages importants pour l’injection de dépendances :
Cet article utilise le projet WPF Gallery pour apprendre à utiliser l'injection de dépendances dans l'adresse du code WPF :
https://github.com/microsoft/WPF-Samples/blob/main/SampleApplications/WPFGallery
Pour implémenter l'injection de dépendances dans ce projet, ces deux packages sont utilisés :
Regardez d’abord le contenu de App.xaml.cs :
public partial class App : Application
{
private static readonly IHost _host = Host.CreateDefaultBuilder()
.ConfigureServices((context, services) =>
{
services.AddSingleton<INavigationService, NavigationService>();
services.AddSingleton<MainWindow>();
services.AddSingleton<MainWindowViewModel>();
services.AddTransient<DashboardPage>();
services.AddTransient<DashboardPageViewModel>();
services.AddTransient<ButtonPage>();
services.AddTransient<ButtonPageViewModel>();
services.AddTransient<CheckBoxPage>();
services.AddTransient<CheckBoxPageViewModel>();
services.AddTransient<ComboBoxPage>();
services.AddTransient<ComboBoxPageViewModel>();
services.AddTransient<RadioButtonPage>();
services.AddTransient<RadioButtonPageViewModel>();
services.AddTransient<SliderPage>();
services.AddTransient<SliderPageViewModel>();
services.AddTransient<CalendarPage>();
services.AddTransient<CalendarPageViewModel>();
services.AddTransient<DatePickerPage>();
services.AddTransient<DatePickerPageViewModel>();
services.AddTransient<TabControlPage>();
services.AddTransient<TabControlPageViewModel>();
services.AddTransient<ProgressBarPage>();
services.AddTransient<ProgressBarPageViewModel>();
services.AddTransient<MenuPage>();
services.AddTransient<MenuPageViewModel>();
services.AddTransient<ToolTipPage>();
services.AddTransient<ToolTipPageViewModel>();
services.AddTransient<CanvasPage>();
services.AddTransient<CanvasPageViewModel>();
services.AddTransient<ExpanderPage>();
services.AddTransient<ExpanderPageViewModel>();
services.AddTransient<ImagePage>();
services.AddTransient<ImagePageViewModel>();
services.AddTransient<DataGridPage>();
services.AddTransient<DataGridPageViewModel>();
services.AddTransient<ListBoxPage>();
services.AddTransient<ListBoxPageViewModel>();
services.AddTransient<ListViewPage>();
services.AddTransient<ListViewPageViewModel>();
services.AddTransient<TreeViewPage>();
services.AddTransient<TreeViewPageViewModel>();
services.AddTransient<LabelPage>();
services.AddTransient<LabelPageViewModel>();
services.AddTransient<TextBoxPage>();
services.AddTransient<TextBoxPageViewModel>();
services.AddTransient<TextBlockPage>();
services.AddTransient<TextBlockPageViewModel>();
services.AddTransient<RichTextEditPage>();
services.AddTransient<RichTextEditPageViewModel>();
services.AddTransient<PasswordBoxPage>();
services.AddTransient<PasswordBoxPageViewModel>();
services.AddTransient<ColorsPage>();
services.AddTransient<ColorsPageViewModel>();
services.AddTransient<LayoutPage>();
services.AddTransient<LayoutPageViewModel>();
services.AddTransient<AllSamplesPage>();
services.AddTransient<AllSamplesPageViewModel>();
services.AddTransient<BasicInputPage>();
services.AddTransient<BasicInputPageViewModel>();
services.AddTransient<CollectionsPage>();
services.AddTransient<CollectionsPageViewModel>();
services.AddTransient<MediaPage>();
services.AddTransient<MediaPageViewModel>();
services.AddTransient<NavigationPage>();
services.AddTransient<NavigationPageViewModel>();
services.AddTransient<TextPage>();
services.AddTransient<TextPageViewModel>();
services.AddTransient<DateAndTimePage>();
services.AddTransient<DateAndTimePageViewModel>();
services.AddTransient<StatusAndInfoPage>();
services.AddTransient<StatusAndInfoPageViewModel>();
services.AddTransient<SamplesPage>();
services.AddTransient<SamplesPageViewModel>();
services.AddTransient<DesignGuidancePage>();
services.AddTransient<DesignGuidancePageViewModel>();
services.AddTransient<UserDashboardPage>();
services.AddTransient<UserDashboardPageViewModel>();
services.AddTransient<TypographyPage>();
services.AddTransient<TypographyPageViewModel>();
services.AddSingleton<IconsPage>();
services.AddSingleton<IconsPageViewModel>();
services.AddSingleton<SettingsPage>();
services.AddSingleton<SettingsPageViewModel>();
services.AddSingleton<AboutPage>();
services.AddSingleton<AboutPageViewModel>();
}).Build();
[STAThread]
public static void Main()
{
_host.Start();
App app = new();
app.InitializeComponent();
app.MainWindow = _host.Services.GetRequiredService<MainWindow>();
app.MainWindow.Visibility = Visibility.Visible;
app.Run();
}
}
Qu’est-ce qu’IHost ?
En C#,IHost
est une interface utilisée dans .NET pour créer et configurer des applicationsHost
résumé conceptuel.IHost
Une interface définit un ensemble de services et de composants requis pour démarrer, exécuter et gérer une application. Il est généralement utilisé avec les applications ASP.NET Core, mais fonctionne également avec d'autres types d'applications .NET, telles que les applications console ou les programmes WPF.
IHost
L'interface se compose deHostBuilder
Implémentation de classe, qui fournit la création et la configuration deIHost
méthodes d'instance.HostBuilder
Vous permet d'ajouter divers services tels que la journalisation, la configuration, les conteneurs d'injection de dépendances, etc., et de configurer le comportement de démarrage et d'arrêt de votre application.
Fournit des méthodes pratiques pour créer des instances Microsoft.Extensions.Hosting.IHostBuilder avec des valeurs par défaut préconfigurées.
Renvoie un IHostBuilder.
Ajoutez des services au conteneur. Cette opération peut être appelée plusieurs fois et ses résultats sont cumulatifs.
La signification du paramètre configureDelegate est de configurer le délégué de Microsoft.Extensions.DependencyInjection.IServiceCollection.
Cette collection sera utilisée pour construire System.IServiceProvider.
Le délégué nécessite deux types de paramètres : HostBuilderContext et IServiceCollection, qui n'ont aucune valeur de retour.
Une expression Lambda qui satisfait le type de délégué est transmise ici.
En C#,() => {}
Est une syntaxe pour les expressions Lambda. Les expressions Lambda sont un wrapper de délégué léger qui vous permet de définir une méthode anonyme et de la transmettre en tant que paramètre à une méthode prenant en charge les délégués ou les arborescences d'expressions.
Les expressions Lambda fournissent un moyen concis de définir des méthodes, et elles sont particulièrement utiles lorsque vous devez transmettre des méthodes en tant que paramètres à d'autres méthodes.
Lors de l'ajout de services, il existe ici deux cycles de vie, en plus de AddSingleton et AddTransient, il existe également AddScoped.
Ces méthodes définissent le cycle de vie du service, c'est-à-dire la manière dont les instances de service sont créées et gérées dans l'application.
AjouterSingleton
AjouterTransient
AjouterScoped
utiliser ces services
Dans la fonction Principale :
démarrer_host
,passer_host.Services.GetRequiredService<MainWindow>();
Obtenez l'instance MainWindow.
En prenant la classe MainWindow comme exemple, affichez le constructeur de MainWindow dans MainWindow.xaml.cs :
public MainWindow(MainWindowViewModel viewModel, IServiceProvider serviceProvider, INavigationService navigationService)
{
_serviceProvider = serviceProvider;
ViewModel = viewModel;
DataContext = this;
InitializeComponent();
Toggle_TitleButtonVisibility();
_navigationService = navigationService;
_navigationService.Navigating += OnNavigating;
_navigationService.SetFrame(this.RootContentFrame);
_navigationService.Navigate(typeof(DashboardPage));
WindowChrome.SetWindowChrome(
this,
new WindowChrome
{
CaptionHeight = 50,
CornerRadius = default,
GlassFrameThickness = new Thickness(-1),
ResizeBorderThickness = ResizeMode == ResizeMode.NoResize ? default : new Thickness(4),
UseAeroCaptionButtons = true
}
);
this.StateChanged += MainWindow_StateChanged;
}
Après avoir supprimé le contenu sans rapport avec ce sujet, le résultat est le suivant :
public MainWindow(MainWindowViewModel viewModel, IServiceProvider serviceProvider, INavigationService navigationService)
{
_serviceProvider = serviceProvider;
ViewModel = viewModel;
_navigationService = navigationService;
}
Avez-vous remarqué que vous n'avez plus besoin de créer ces objets vous-même ? La création de ces objets est gérée par le conteneur d'injection de dépendances. Lorsque ces objets sont nécessaires, ils peuvent être injectés via le constructeur comme maintenant.
Si l’injection de dépendances n’est pas utilisée, cela pourrait ressembler à ceci :
public MainWindow()
{
_serviceProvider = new IServiceProvider();
ViewModel = new MainWindowViewModel();
_navigationService = new INavigationService();
}
Cet article présente d'abord le concept d'injection de dépendances, puis explique pourquoi l'injection de dépendances est nécessaire et apprend enfin comment utiliser l'injection de dépendances dans WPF via le projet WPF Gallery.
1. [Exemples WPF/Exemples d'applications/WPFGallery sur le site principal · microsoft/Exemples WPF (github.com)](https://github.com/microsoft/WPF-Samples/tree/main/Exemples d'applications/WPFGallery)