依赖注入通过外部注入对象实现解耦,提升代码可测试性与维护性。示例中UserService不再自行创建UserDataAccess,而是通过构造函数接收IUserDataAccess实现,.NET内置容器在Program.cs中注册服务生命周期(Scoped/Singleton/Transient),运行时自动注入实例,测试时可替换为Mock对象,避免硬编码依赖,统一管理对象创建,降低耦合度。
依赖注入(Dependency Injection,简称 DI)是 C# 和 .NET 开发中一个非常重要的设计模式。它帮助我们写出更松耦合、更容易测试和维护的代码。如果你刚接触这个概念,可能会觉得抽象,但其实它的核心思想很简单:不要自己创建对象,而是让外部系统把需要的对象“送进来”。
在面向对象编程中,一个类经常需要使用另一个类的功能。比如,有一个 UserService 类需要访问数据库,它可能依赖于一个 UserDataAccess 类。这种“需要别人帮忙完成工作”的关系就是“依赖”。
示例:
假设你有一个用户服务类:
public class UserService
{
private UserDataAccess _dataAccess;
public UserService()
{
_dataAccess = new UserDataAccess(); // 手动创建依赖
}
public string GetUser(int id)
{
return _dataAccess.GetUserById(id);
}}
这里的问题是:UserService 自己创建了 UserDataAccess,导致两者紧紧绑在一起。如果将来想换成 Mock 数据或不同的实现,就必须修改代码 —— 这不利于测试和扩展。
依赖注入的核心思想
DI 的基本思路是:把依赖项从外部“注入”进来,而不是在类内部自己 new 出来。最常见的方式是通过构造函数传入。
改写上面的例子:
public class UserService
{
private readonly IUserDataAccess _dataAccess;
public UserService(IUserDataAccess dataAccess) // 依赖通过构造函数传入
{
_dataAccess = dataAccess;
}
public string GetUser(int id)
{
return _dataAccess.GetUserById(id);
}}
现在,UserService 不关心具体是谁提供数据访问功能,只要对方符合 IUserDataAccess 接口就行。这就实现了“解耦”。
.NET 中的内置 DI 容器
.NET Core 及以后版本内置了依赖注入容器,可以在程序启动时注册服务,并自动把它们注入到需要的地方。
步骤如下:
完整示例:
// 1. 定义接口
public interface IUserDataAccess
{
string GetUserById(int id);
}
// 2. 实现接口
public class UserDataAccess : IUserDataAccess
{
public string GetUserById(int id)
{
return $"User {id} from database";
}
}
// 3. 使用依赖的服务
public class UserService
{
private readonly IUserDataAccess _dataAccess;
public UserService(IUserDataAccess dataAccess)
{
_dataAccess = dataAccess;
}
public string GetUser(int id)
{
return _dataAccess.GetUserById(id);
}}
在 Program.cs(.NET 6+)中注册服务:
var builder = WebApplication.CreateBuilder(args);
// 注册服务:告诉容器 IUserDataAccess 应该用 UserDataAccess 来实例化
builder.Services.AddScoped();
builder.Services.AddScoped();
var app = builder.Build();
// 示例:在 Minimal API 中使用
app.MapGet("/user/{id}", (int id, UserService userService) =>
{
return userService.GetUser(id);
});
app.Run();
当你访问 /user/1 时,.NET 会自动创建 UserService 实例,并把已注册的 IUserDataAccess 实现注入进去。
三种常见的服务生命周期
注册服务时,你需要选择它的生命周期:
一般情况下:
现时只需修改注册代码,无需改动业务类举个测试的例子:
// 测试时可以注入一个假的数据访问层
public class MockUserDataAccess : IUserDataAccess
{
public string GetUserById(int id) => $"Mock User {id}";
}
// 单元测试中
var mockDataAccess = new MockUserDataAccess();
var userService = new UserService(mockDataAccess); // 注入模拟对象
var result = userService.GetUser(1);
Console.WriteLine(result); // 输出: Mock User 1
这样不需要真实数据库就能测试逻辑。
基本上就这些。依赖注入不是魔法,它只是一个帮你更好地组织代码的工具。刚开始可能会觉得多写了不少接口和注册代码,但随着项目变大,你会发现它带来的清晰结构和灵活性非常值得。
# 编码
# app
# access
# 工具
# 面向对象编程
# c#
# 数据访问
# .net
# 为什么
# 面向对象
# 构造函数
# 接口
# 对象
# 数据库
# http
# 是一个
# 如果你
# 是在
# 你可以
# 就能
# 不需要
# 当你
# 只需
# 帮你
# 适用于
相关文章:
建站之星代理如何优化在线客服效率?
网站制作免费,什么网站能看正片电影?
建站之星ASP如何实现CMS高效搭建与安全管理?
建站之星在线客服如何快速接入解答?
洛阳网站制作公司有哪些,洛阳的招聘网站都有哪些?
建站之星免费模板:自助建站系统与智能响应式一键生成
可靠的网站设计制作软件,做网站设计需要什么样的电脑配置?
高配服务器限时抢购:企业级配置与回收服务一站式优惠方案
为什么Go需要go mod文件_Go go mod文件作用说明
大型企业网站制作流程,做网站需要注册公司吗?
建站ABC备案流程中有哪些关键注意事项?
微信小程序 五星评分(包括半颗星评分)实例代码
相亲简历制作网站推荐大全,新相亲大会主持人小萍萍资料?
定制建站策划方案_专业建站与网站建设方案一站式指南
,怎么在广州志愿者网站注册?
如何在Golang中指定模块版本_使用go.mod控制版本号
建站OpenVZ教程与优化策略:配置指南与性能提升
javascript基本数据类型及类型检测常用方法小结
焦点电影公司作品,电影焦点结局是什么?
网站制作培训多少钱一个月,网站优化seo培训课程有哪些?
如何用西部建站助手快速创建专业网站?
保定网站制作方案定制,保定招聘的渠道有哪些?找工作的人一般都去哪里看招聘信息?
建站之星后台密码遗忘?如何快速找回?
西安制作网站公司有哪些,西安货运司机用的最多的app或者网站是什么?
标准网站视频模板制作软件,现在有哪个网站的视频编辑素材最齐全的,背景音乐、音效等?
胶州企业网站制作公司,青岛石头网络科技有限公司怎么样?
南宁网站建设制作定制,南宁网站建设可以定制吗?
网站建设设计制作营销公司南阳,如何策划设计和建设网站?
模具网站制作流程,如何找模具客户?
专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?
交易网站制作流程,我想开通一个网站,注册一个交易网址,需要那些手续?
广东企业建站网站优化与SEO营销核心策略指南
导航网站建站方案与优化指南:一站式高效搭建技巧解析
如何在阿里云虚拟服务器快速搭建网站?
,在苏州找工作,上哪个网站比较好?
智能起名网站制作软件有哪些,制作logo的软件?
如何制作一个表白网站视频,关于勇敢表白的小标题?
建站之星后台密码如何安全设置与找回?
实现点击下箭头变上箭头来回切换的两种方法【推荐】
移动端手机网站制作软件,掌上时代,移动端网站的谷歌SEO该如何做?
台州网站建设制作公司,浙江手机无犯罪记录证明怎么开?
如何通过.red域名打造高辨识度品牌网站?
建站为何优先选择香港服务器?
PHP 500报错的快速解决方法
h5网站制作工具有哪些,h5页面制作工具有哪些?
头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?
如何通过西部数码建站助手快速创建专业网站?
太平洋网站制作公司,网络用语太平洋是什么意思?
C++中的Pimpl idiom是什么,有什么好处?(隐藏实现)
视频网站制作教程,怎么样制作优酷网的小视频?
*请认真填写需求信息,我们会在24小时内与您取得联系。