【C#】依赖注入知识点汇总

在C#中实现依赖注入(Dependency Injection, DI)可以帮助你创建更解耦、可维护和易于测试的软件系统。以下是一些关于依赖注入的关键知识点及其示例代码。

 

1. 基本概念

容器 (Container)

容器负责管理对象实例以及它们之间的依赖关系。

 

IoC容器(Inversion of Control Container)是实现依赖注入的核心工具,常见的DI框架包括Unity、Autofac、Castle Windsor等。

注入点 (Injection Points)

注入点是指需要由容器提供所需对象的地方:

 

构造函数

属性

方法参数

 

2. 关键知识点

服务接口和服务实现

定义一个或多个服务接口,并为这些接口提供具体的实现。

public interface IUserService

{

    User GetUser(int id);

}

 

public class UserService : IUserService

{

    public User GetUser(int id)

    {

        return new User { Id = id, Name = "John Doe", Age = 30 };

    }

}

 

注册服务到容器

在DI容器中注册服务及其实现。

using Microsoft.Practices.Unity;

 

public class Bootstrapper

{

    public IUnityContainer ConfigureContainer()

    {

        var container = new UnityContainer();

 

        // 注册 UserService 实现 IUserService 接口,并使用单例生命周期管理器

        container.RegisterType(new ContainerControlledLifetimeManager());

 

        return container;

    }

}

 

解析服务并注入依赖

在需要的地方解析并注入已注册的服务。

public class UserViewModel : INotifyPropertyChanged

{

    private readonly IUserService _userService;

 

    public event PropertyChangedEventHandler PropertyChanged;

 

    protected void OnPropertyChanged(string name)

    {

        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));

    }

 

    public UserViewModel(IUserService userService)

    {

        _userService = userService;

    }

}

 

3. 示例代码

定义服务接口和服务实现

public interface IUserService

{

    User GetUser(int id);

}

 

public class UserService : IUserService

{

    public User GetUser(int id)

    {

        return new User { Id = id, Name = "John Doe", Age = 30 };

    }

}

 

配置容器并注册服务

using Microsoft.Practices.Unity;

 

public static class ContainerConfigurator

{

    public static IUnityContainer Configure()

    {

        var container = new UnityContainer();

 

        // 注册 UserService 实现 IUserService 接口,并使用单例生命周期管理器

        container.RegisterType(new ContainerControlledLifetimeManager());

 

        return container;

    }

}

 

解析服务并注入依赖

public class UserViewModel : INotifyPropertyChanged

{

    private readonly IUserService _userService;

 

    public event PropertyChangedEventHandler PropertyChanged;

 

    protected void OnPropertyChanged(string name)

    {

        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));

    }

 

    public UserViewModel(IUserService userService)

    {

        _userService = userService;

    }

 

    public User User { get; set; }

 

    public void LoadUser(int id)

    {

        User = _userService.GetUser(id);

        OnPropertyChanged(nameof(User));

    }

}

 

在应用程序中使用依赖注入

public class AppBootstrapper : Application

{

    protected override void OnStartup(StartupEventArgs e)

    {

        base.OnStartup(e);

 

        var container = ContainerConfigurator.Configure();

 

        // 创建 UserViewModel 并设置为 MainWindow 的 DataContext

        var viewModel = container.Resolve();

        MainWindow mainWindow = new MainWindow { DataContext = viewModel };

        mainWindow.Show();

    }

}

 

4. 生命周期管理

单例 (Singleton)

每个类型在容器中只有一个实例。

container.RegisterType(new ContainerControlledLifetimeManager());

瞬态 (Transient)

每次请求都会创建一个新的对象实例。

container.RegisterType();

容器控制的瞬态 (Per-Container Transient)

每个容器只有一个实例,即使从多个上下文访问它也会只返回一个实例。

container.RegisterType(new PerResolveLifetimeManager());

 

5. 属性注入和构造函数注入

构造函数注入

依赖项通过构造函数注入到类中。

public class UserViewModel : INotifyPropertyChanged

{

    private readonly IUserService _userService;

 

    public event PropertyChangedEventHandler PropertyChanged;

 

    protected void OnPropertyChanged(string name)

    {

        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));

    }

 

    public UserViewModel(IUserService userService)

    {

        _userService = userService;

    }

}

 

属性注入

依赖项通过属性进行注入。

public class UserViewModel : INotifyPropertyChanged

{

    private readonly IUserService _userService;

 

    [Dependency]

    public IUserService UserService

    {

        get { return _userService; }

        set { _userService = value; }

    }

 

    // 构造函数或其他方法可以省略,依赖项会自动注入到属性中。

}

 

6. 使用Unity进行配置

配置和注册服务

using Microsoft.Practices.Unity;

 

public class Bootstrapper

{

    public IUnityContainer Configure()

    {

        var container = new UnityContainer();

 

        // 注册UserService实现IUserService接口,并使用单例生命周期管理器

        container.RegisterType(new ContainerControlledLifetimeManager());

 

        return container;

    }

}

 

解析并注入服务到ViewModel

public class AppBootstrapper : Application

{

    protected override void OnStartup(StartupEventArgs e)

    {

        base.OnStartup(e);

 

        var container = Bootstrapper.Configure();

 

        // 创建UserViewModel,并设置为MainWindow的DataContext

        var viewModel = container.Resolve();

        MainWindow mainWindow = new MainWindow { DataContext = viewModel };

        mainWindow.Show();

    }

}

 

总结

通过以上示例和知识点,你可以更好地理解和实现依赖注入。依赖注入可以显著提高代码的可测试性和模块化程度,从而简化维护工作并加快开发进度。

 

你可能感兴趣的:(c#)