宁波外贸网站建设少儿编程
一、依赖注入的核心原理
-
控制反转(Inversion of Control, IoC)
- 核心思想:将对象的创建和依赖管理从代码内部转移到外部容器,控制权由容器接管。
- 示例:在 WPF 中,
MainViewModel
不直接创建IDataService
,而是通过容器注入。 - 实现方式:通过构造函数、属性或方法注入依赖项,容器负责解析依赖关系并实例化对象。
-
依赖管理机制
- 依赖图:容器根据对象间的依赖关系构建有向图,确保正确的创建顺序。
- 生命周期管理:支持单例(Singleton)、瞬态(Transient)、作用域(Scoped)等模式。
- 单例:全局唯一实例(如日志服务)。
- 瞬态:每次请求创建新实例(如临时数据处理服务)。
- 作用域:在特定上下文(如 HTTP 请求)内共享实例。
-
松耦合设计
- 通过接口定义服务,实现类与调用者解耦。例如,
MockDataService
实现IDataService
,当需要切换数据源时,只需替换实现类而不影响调用方。
- 通过接口定义服务,实现类与调用者解耦。例如,
二、依赖注入的核心原则
-
依赖倒置原则(Dependency Inversion Principle, DIP)
- 高层模块不依赖底层模块,两者均依赖抽象。
- 示例:
MainViewModel
依赖IDataService
接口,而非具体的MockDataService
类。 - 作用:提高代码灵活性,支持运行时动态替换服务实现。
-
单一职责原则(Single Responsibility Principle, SRP)
- 每个类仅负责单一功能,依赖由外部注入。
- 示例:
ConsoleLoggerService
专注日志记录,MockDataService
专注数据获取,通过构造函数注入协作。
-
构造函数注入优先
- 通过构造函数明确声明依赖,确保对象初始化时依赖已准备好。
- 反模式:避免使用属性注入(Setter Injection)或字段注入(Field Injection),因为可能导致未初始化的依赖。
-
显式依赖原则
- 依赖关系必须显式声明,而非隐式查找(如通过全局服务定位器)。
- 优势:提高代码可读性,便于静态分析和测试。
案例一:
MainWindow.xaml
<Window x:Class="UserApp.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="User App" Height="350" Width="525"><Grid><StackPanel Orientation="Vertical" Margin="20"><TextBox Text="{Binding NewName, UpdateSourceTrigger=PropertyChanged}" PlaceholderText="Enter user name" /><TextBox Text="{Binding NewAge, UpdateSourceTrigger=PropertyChanged}" PlaceholderText="Enter user age" /><Button Content="Add User" Command="{Binding AddUserCommand}" /><ListBox ItemsSource="{Binding Users}"><ListBox.ItemTemplate><DataTemplate><StackPanel Orientation="Horizontal"><TextBlock Text="{Binding Name}" Margin="5" /><TextBlock Text=" - " Margin="5" /><TextBlock Text="{Binding Age}" Margin="5" /></StackPanel></DataTemplate></ListBox.ItemTemplate></ListBox></StackPanel></Grid>
</Window>
MainWindow.xaml.cs
using Microsoft.Extensions.DependencyInjection;
using System.Windows;namespace UserApp
{public partial class MainWindow : Window{public MainWindow(){InitializeComponent();var serviceCollection = new ServiceCollection();serviceCollection.AddSingleton<IUserService, UserService>();serviceCollection.AddSingleton<UserViewModel>();var serviceProvider = serviceCollection.BuildServiceProvider();DataContext = serviceProvider.GetRequiredService<UserViewModel>();}}
}
UserService.cs
using System.Collections.Generic;// 用户服务接口
public interface IUserService
{List<User> GetUsers();void AddUser(User user);
}// 用户类
public class User
{public string Name { get; set; }public int Age { get; set; }
}// 用户服务实现类
public class UserService : IUserService
{private readonly List<User> _users = new List<User>();public List<User> GetUsers(){return _users;}public void AddUser(User user){_users.Add(user);}
}
UserViewModel.cs
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;// 用户视图模型
public class UserViewModel : INotifyPropertyChanged
{private readonly IUserService _userService;public ObservableCollection<User> Users { get; set; }private string _newName;private int _newAge;public string NewName{get { return _newName; }set{_newName = value;OnPropertyChanged();}}public int NewAge{get { return _newAge; }set{_newAge = value;OnPropertyChanged();}}public UserViewModel(IUserService userService){_userService = userService;Users = new ObservableCollection<User>(_userService.GetUsers());}public void AddNewUser(){if (!string.IsNullOrEmpty(NewName) && NewAge > 0){var newUser = new User { Name = NewName, Age = NewAge };_userService.AddUser(newUser);Users.Add(newUser);NewName = string.Empty;NewAge = 0;}}public event PropertyChangedEventHandler PropertyChanged;protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}
}
案例二
Book.cs
namespace WpfMvvmDiExample.Models
{public class Book{public string Title { get; set; }public string Author { get; set; }}
}
BookService.cs
using System.Collections.Generic;
using WpfMvvmDiExample.Models;namespace WpfMvvmDiExample.Services
{public class BookService : IBookService{private readonly List<Book> _books = new List<Book>();public List<Book> GetBooks(){return _books;}public void AddBook(Book book){_books.Add(book);}}
}
IBookService.cs
using System.Collections.Generic;namespace WpfMvvmDiExample.Services
{public interface IBookService{List<Book> GetBooks();void AddBook(Book book);}
}
BookViewModel.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using WpfMvvmDiExample.Models;
using WpfMvvmDiExample.Services;namespace WpfMvvmDiExample.ViewModels
{public class BookViewModel : INotifyPropertyChanged{private readonly IBookService _bookService;public ObservableCollection<Book> Books { get; set; }private string _newTitle;private string _newAuthor;public string NewTitle{get { return _newTitle; }set{_newTitle = value;OnPropertyChanged();}}public string NewAuthor{get { return _newAuthor; }set{_newAuthor = value;OnPropertyChanged();}}public BookViewModel(IBookService bookService){_bookService = bookService;Books = new ObservableCollection<Book>(_bookService.GetBooks());}public void AddNewBook(){if (!string.IsNullOrEmpty(NewTitle) && !string.IsNullOrEmpty(NewAuthor)){var newBook = new Book { Title = NewTitle, Author = NewAuthor };_bookService.AddBook(newBook);Books.Add(newBook);NewTitle = string.Empty;NewAuthor = string.Empty;}}public event PropertyChangedEventHandler PropertyChanged;protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}}
}
App.xaml.cs
using Microsoft.Extensions.DependencyInjection;
using System.Windows;
using WpfMvvmDiExample.Services;
using WpfMvvmDiExample.ViewModels;namespace WpfMvvmDiExample
{public partial class App : Application{private readonly ServiceProvider _serviceProvider;public App(){var serviceCollection = new ServiceCollection();ConfigureServices(serviceCollection);_serviceProvider = serviceCollection.BuildServiceProvider();}private void ConfigureServices(ServiceCollection services){services.AddSingleton<IBookService, BookService>();services.AddSingleton<BookViewModel>();services.AddTransient<MainWindow>();}protected override void OnStartup(StartupEventArgs e){base.OnStartup(e);var mainWindow = _serviceProvider.GetRequiredService<MainWindow>();mainWindow.Show();}}
}
MainWindow.xaml
<Window x:Class="WpfMvvmDiExample.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="Book Management App" Height="350" Width="525"><Grid><StackPanel Orientation="Vertical" Margin="20"><TextBox Text="{Binding NewTitle, UpdateSourceTrigger=PropertyChanged}" PlaceholderText="Enter book title" /><TextBox Text="{Binding NewAuthor, UpdateSourceTrigger=PropertyChanged}" PlaceholderText="Enter book author" /><Button Content="Add Book" Click="AddBookButton_Click" /><ListBox ItemsSource="{Binding Books}"><ListBox.ItemTemplate><DataTemplate><StackPanel Orientation="Horizontal"><TextBlock Text="{Binding Title}" Margin="5" /><TextBlock Text=" - " Margin="5" /><TextBlock Text="{Binding Author}" Margin="5" /></StackPanel></DataTemplate></ListBox.ItemTemplate></ListBox></StackPanel></Grid>
</Window>
MainWindow.xaml.cs
using Microsoft.Extensions.DependencyInjection;
using System.Windows;
using WpfMvvmDiExample.ViewModels;namespace WpfMvvmDiExample
{public partial class MainWindow : Window{private readonly BookViewModel _viewModel;public MainWindow(BookViewModel viewModel){InitializeComponent();_viewModel = viewModel;DataContext = _viewModel;}private void AddBookButton_Click(object sender, RoutedEventArgs e){_viewModel.AddNewBook();}}
}