.net 的依赖注入(Dependency Injection,简称 DI)

.net 的依赖注入(Dependency Injection,简称 DI)是一种设计模式,其目的是将对象的依赖关系从对象本身解耦。



.NET 中的依赖注入(Dependency Injection,DI)通过以下几种关键机制来实现对象解耦:

1、 传统方式:紧耦合

这种写法问题
1、代码高度依赖具体实现
2、难以更换数据库类型
3、不易进行单元测试
4、模块间强耦合

public class UserService {  
  // 直接依赖具体实现,导致高度耦合  
    // 直接依赖具体实现,导致高度耦合  
    private SqlServerDatabase _database = new SqlServerDatabase();  

    public void SaveUser(User user) {  
        _database.Save(user);  
    }  
}  

2、依赖注入的解耦方案


// 定义抽象接口  
public interface IDatabase {  
    void Save(User user);  
}  

// 具体实现解耦  
public class SqlServerDatabase : IDatabase {  
    public void Save(User user) {  
        // SQL Server 存储逻辑  
    }  
}  

public class MySqlDatabase : IDatabase {  
    public void Save(User user) {  
        // MySQL 存储逻辑  
    }  
}  

// 依赖注入的服务  
public class UserService {  
    // 依赖抽象,而非具体实现  
    private readonly IDatabase _database;  

    // 通过构造函数注入依赖  
    public UserService(IDatabase database) {  
        _database = database;  
    }  

    public void SaveUser(User user) {  
        // 可以使用任何实现了IDatabase的具体类  
        _database.Save(user);  
    }  
}

3、依赖注入的核心解耦机制

解耦机制包括:
a. 面向接口编程
b. 依赖倒置原则
c. 控制反转

// 依赖倒置原则示例  
public interface ILogger {  
    void Log(string message);  
}  

public class UserService {  
    private readonly ILogger _logger;  
    private readonly IDatabase _database;  

    // 通过构造函数解耦  
    public UserService(  
        ILogger logger,   
        IDatabase database  
    ) {  
        _logger = logger;  
        _database = database;  
    }  

    public void Process(User user) {  
        // 解耦:可以使用任何日志和数据库实现  
        _logger.Log("Processing user");  
        _database.Save(user);  
    }  
}

切换 例如通过配置方式实现

// 接口定义  
public interface IDatabase {  
    void Save(User user);  
}  

// MySQL 实现  
public class MySqlDatabase : IDatabase {  
    public void Save(User user) {  
        // MySQL 存储逻辑  
    }  
}  

// SQLServer 实现  
public class SqlServerDatabase : IDatabase {  
    public void Save(User user) {  
        // SQLServer 存储逻辑  
    }  
}  

// 启动配置  
public void ConfigureServices(IServiceCollection services) {  
    // 方式1:通过配置文件动态选择  
    var databaseType = Configuration["DatabaseType"];  
    
    switch (databaseType) {  
        case "MySQL":  
            services.AddScoped<IDatabase, MySqlDatabase>();  
            break;  
        case "SQLServer":  
            services.AddScoped<IDatabase, SqlServerDatabase>();  
            break;  
        default:  
            throw new Exception("未知数据库类型");  
    }  

    // 方式2:hardcode方式  
    // services.AddScoped<IDatabase, MySqlDatabase>();  
}

4、依赖注入容器的工作原理

// 依赖注入容器配置  
public void ConfigureServices(IServiceCollection services) {  
    // 注册服务的不同生命周期  
    
    // 瞬时:每次请求都创建新实例  
    services.AddTransient<IDatabase, SqlServerDatabase>();  
    
    // 作用域:每个请求周期一个实例  
    services.AddScoped<ILogger, FileLogger>();  
    
    // 单例:全局唯一实例  
    services.AddSingleton<IConfigService, AppConfigService>();  

    // 注册服务  
    services.AddScoped<UserService>();  
}

5、依赖注入的优势

// 优势体现  
public class TestUserService {  
    // 可以轻松进行单元测试  
    public void TestSaveUser() {  
        // 使用模拟对象  
        var mockDatabase = new Mock<IDatabase>();  
        var mockLogger = new Mock<ILogger>();  

        var userService = new UserService(  
            mockLogger.Object,   
            mockDatabase.Object  
        );  

        // 验证逻辑  
        userService.Process(new User());  
        
        // 校验交互  
        mockDatabase.Verify(db => db.Save(It.IsAny<User>()), Times.Once);  
    }  
}

6、完整解耦示例

// 抽象定义  
public interface IPaymentGateway {  
    bool ProcessPayment(decimal amount);  
}  

public interface INotificationService {  
    void SendConfirmation(string message);  
}  

// 具体实现  
public class StripePaymentGateway : IPaymentGateway {  
    public bool ProcessPayment(decimal amount) {  
        // Stripe支付逻辑  
        return true;  
    }  
}  

public class EmailNotificationService : INotificationService {  
    public void SendConfirmation(string message) {  
        // 发送邮件通知  
    }  
}  

// 订单服务  
public class OrderService {  
    private readonly IPaymentGateway _paymentGateway;  
    private readonly INotificationService _notificationService;  

    // 解耦:通过构造函数注入依赖  
    public OrderService(  
        IPaymentGateway paymentGateway,  
        INotificationService notificationService  
    ) {  
        _paymentGateway = paymentGateway;  
        _notificationService = notificationService;  
    }  

    public void PlaceOrder(Order order) {  
        // 解耦的业务逻辑  
        if (_paymentGateway.ProcessPayment(order.Total)) {  
            _notificationService.SendConfirmation("订单成功");  
        }  
    }  
}

总结

关键解耦原理总结:

依赖抽象接口,而非具体实现
通过外部注入依赖
使用接口定义契约
利用依赖注入容器管理对象生命周期
降低模块间直接耦合
这种设计使代码:

更加灵活
易于测试
方便扩展
解耦各个组件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值