minhas informações de contato
Correspondência[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Este artigo usa o projeto Galeria WPF para aprender os conceitos relacionados à injeção de dependência e como executar a injeção de dependência no WPF.
Injeção de Dependência (DI) é um padrão de design usado para implementar o princípio de Inversão de Controle (IoC). O principal objetivo da injeção de dependência é transferir a criação de objetos e o gerenciamento de dependências entre objetos de dentro do objeto para um contêiner ou estrutura externa, melhorando assim a capacidade de manutenção, testabilidade e flexibilidade do código.
O conceito central de injeção de dependência
Tipos de injeção de dependência
injeção de construtor: O objeto dependente é passado pelo construtor da classe.
public class OrderService
{
private readonly IProductRepository _productRepository;
public OrderService(IProductRepository productRepository)
{
_productRepository = productRepository;
}
}
Injeção de propriedade: objetos dependentes são passados pelas propriedades públicas da classe.
public class OrderService
{
public IProductRepository ProductRepository { get; set; }
}
injeção de método: O objeto dependente é passado pelo parâmetro do método da classe.
public class OrderService
{
public void ProcessOrder(IProductRepository productRepository)
{
// 使用 productRepository 处理订单
}
}
Injeção de Dependência (DI) é um padrão de design por meio do qual a criação de objetos e o gerenciamento de dependências entre objetos podem ser transferidos de dentro do objeto para um contêiner ou estrutura externa. Existem vários motivos e vantagens importantes para a injeção de dependência:
Este artigo usa o projeto Galeria WPF para aprender como usar injeção de dependência no endereço de código WPF:
https://github.com/microsoft/WPF-Samples/blob/main/SampleApplications/WPFGallery
Para implementar a injeção de dependência neste projeto, estes dois pacotes são usados:
Primeiro, observe o conteúdo 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();
}
}
O que é IHost?
Em C#,IHost
é uma interface usada em .NET para construir e configurar aplicativosHost
conceito abstrato.IHost
Uma interface define uma coleção de serviços e componentes necessários para iniciar, executar e gerenciar um aplicativo. Normalmente é usado com aplicativos ASP.NET Core, mas também funciona com outros tipos de aplicativos .NET, como aplicativos de console ou programas WPF.
IHost
A interface consiste emHostBuilder
Implementação de classe, que fornece a criação e configuração deIHost
métodos de instância.HostBuilder
Permite adicionar vários serviços, como registro, configuração, contêineres de injeção de dependência, etc., e configurar o comportamento de inicialização e parada de seu aplicativo.
Fornece métodos convenientes para criar instâncias Microsoft.Extensions.Hosting.IHostBuilder com padrões pré-configurados.
Retorna um IHostBuilder.
Adicione serviços ao contêiner. Esta operação pode ser chamada diversas vezes e seus resultados são cumulativos.
O significado do parâmetro configureDelegate é configurar o delegado de Microsoft.Extensions.DependencyInjection.IServiceCollection.
Esta coleção será usada para construir System.IServiceProvider.
O delegado requer dois tipos de parâmetros: HostBuilderContext e IServiceCollection, que não possuem valor de retorno.
Uma expressão Lambda que satisfaça o tipo delegado é passada aqui.
Em C#,() => {}
É uma sintaxe para expressões Lambda. As expressões lambda são um wrapper de delegado leve que permite definir um método anônimo e passá-lo como parâmetro para um método que oferece suporte a delegados ou árvores de expressão.
As expressões lambda fornecem uma maneira concisa de definir métodos e são úteis especialmente quando você precisa passar métodos como parâmetros para outros métodos.
Ao adicionar serviços, existem dois ciclos de vida aqui, além de AddSingleton e AddTransient, há também AddScoped.
Esses métodos definem o ciclo de vida do serviço, ou seja, como as instâncias de serviço são criadas e gerenciadas na aplicação.
Adicionar Singleton
Adicionar Transiente
Adicionar escopo
use esses serviços
Na função principal:
comece_host
,passar_host.Services.GetRequiredService<MainWindow>();
Obtenha a instância MainWindow.
Tomando a classe MainWindow como exemplo, visualize o construtor de MainWindow em 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;
}
Após a remoção do conteúdo irrelevante para este tópico, fica o seguinte:
public MainWindow(MainWindowViewModel viewModel, IServiceProvider serviceProvider, INavigationService navigationService)
{
_serviceProvider = serviceProvider;
ViewModel = viewModel;
_navigationService = navigationService;
}
Você notou que não precisa mais criar esses objetos sozinho. A criação desses objetos é gerenciada pelo contêiner de injeção de dependência. Quando esses objetos são necessários, eles podem ser injetados através do construtor como agora.
Se a injeção de dependência não for usada, poderá ficar assim:
public MainWindow()
{
_serviceProvider = new IServiceProvider();
ViewModel = new MainWindowViewModel();
_navigationService = new INavigationService();
}
Este artigo primeiro apresenta o conceito de injeção de dependência, depois explica por que a injeção de dependência é necessária e, finalmente, aprende como usar a injeção de dependência no WPF por meio do projeto Galeria WPF.
1、[Amostras WPF/Aplicativos de amostra/WPFGallery na página principal · microsoft/WPF-Samples (github.com)](https://github.com/microsoft/WPF-Samples/tree/main/Aplicativos de amostra/WPFGallery)