尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

02020212 .NET Core重难点知识12-服务定位器、.NET依赖注入示例

02020212 .NET  Core重难点知识12-服务定位器、.NET依赖注入示例
📅 发布时间:2026/6/19 8:01:26

02020212 .NET Core重难点知识12-服务定位器、.NET依赖注入示例

1. 服务定位器(视频Part2-27)

1.1 IServiceProvider的服务定位器方法
T GetService<T>() → 如果获取不到对象,则返回null。
object GetService(Type serviceType)
T GetRequiredService<T>() → 如果获取不到对象,则抛异常。
object GetRequiredService(Type serviceType)
IEnumerable<T> GetServices<T>() → 适用于可能有很多满足条件的服务。
IEnumerable<object> GetService(Type serviceType)
1.2 其它注册方法
  • 服务类型和实现类型不一致的注册。
  • 简单看看其它Add方法。
1.3 GetService()注册方法
using Microsoft.Extensions.DependencyInjection;
using System;namespace Demo02
{public interface ITestService{public string Name { get; set; }public void SayHi();}public class TestServiceImp1 : ITestService, IDisposable{public string Name { get; set; }public void Dispose(){Console.WriteLine("Dispose...");}public void SayHi(){Console.WriteLine($"Hi! I'm {Name}");}}class Program{static void Main(string[] args){ServiceCollection services = new ServiceCollection();services.AddScoped<ITestService, TestServiceImp1>(); // @1 // services.AddScoped<typeof(ITestService), typeof(TestServiceImp1)>(); // @2// services.AddSingleton<ITestService, TestServiceImp1>(); // @3// services.AddSingleton<typeof(ITestService), new TestServiceImp1()>; // @4 TestServiceImp1构造函数可以添加参数using (ServiceProvider sp = services.BuildServiceProvider()){ITestService ts1 = sp.GetService<ITestService>(); // @5 返回的是实现类的对象// TestServiceImp1 ts1 = sp.GetService<TestServiceImp1>(); // @6 返回的是实现类的对象ts1.Name = "Qinway";ts1.SayHi();Console.WriteLine(ts1);}Console.ReadLine();}}
}控制台输出:
Hi! I'm Qinway
Demo02.TestServiceImp1
Dispose...说明:
1. 在@1处两个泛型:ITestService表示服务类型(接口),实现类型TestServiceImp1(实现类)。此时不管实现类是什么,我只要接口的服务。
2. 随着项目变得复杂,写注册服务的人(ITestService)和写实现服务的人(TestServiceImp1),可能不是同一个人来做的。
3. 在@1处和@2处两种写法等价。
4. 在@4处,直接将实现类new好了,这样适用于对象需要传递某个参数的时候使用。可以在构造函数添加参数,由开发者自己控制创建对象的条件。
5. 如果采用@4处的注册形式,那么不用用@5处的获取形式,而是要采用@6处的获取形式。注册类型是实现类,那么拿的时候也是实现类。
6. 在@5和@6处,如果GetService找不到服务,就返回null。
7. GetService方法还有非泛型的方法重载,一般不用。
1.3 GetRequiredService()注册方法
using Microsoft.Extensions.DependencyInjection;
using System;namespace Demo02
{public interface ITestService{public string Name { get; set; }public void SayHi();}public class TestServiceImp1 : ITestService, IDisposable{public string Name { get; set; }public void Dispose(){Console.WriteLine("Dispose...");}public void SayHi(){Console.WriteLine($"Hi! I'm {Name}");}}class Program{static void Main(string[] args){ServiceCollection services = new ServiceCollection();services.AddScoped<ITestService, TestServiceImp1>();using (ServiceProvider sp = services.BuildServiceProvider()){TestServiceImp1 ts1 = sp.GetRequiredService<TestServiceImp1>(); // 抛出异常ts1.Name = "Qinway";ts1.SayHi();Console.WriteLine(ts1);}Console.ReadLine();}}
}异常信息:System.InvalidOperationException:“No service for type 'Demo02.TestServiceImp1' has been registered.”说明:GetRequiredService方法不会返回null,这个方法本身就会抛出异常。对比:GetService方法如果找不到,返回null;GetRequiredService如果找不到,抛出异常。这里和C#基础知识显式类型转换(如果不能转换抛异常)和as转换(如果不能转换返回null)类似。
1.4 GetServices()注册方法
  • 该方法适用于实现一个接口有多个服务的情况,如果实现一个接口有多个服务,那么将服务都返回。
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;namespace Demo02
{public interface ITestService{public string Name { get; set; }public void SayHi();}public class TestServiceImp1 : ITestService, IDisposable{public string Name { get; set; }public void Dispose(){Console.WriteLine("Dispose...");}public void SayHi(){Console.WriteLine($"Hi! I'm {Name}");}}public class TestServiceImp2 : ITestService{public string Name { get; set; }public void SayHi(){Console.WriteLine($"你好,我是{Name}");}}class Program{static void Main(string[] args){ServiceCollection services = new ServiceCollection();services.AddScoped<ITestService, TestServiceImp1>(); // 注册第一个services.AddScoped<ITestService, TestServiceImp2>(); // 注册第二个using (ServiceProvider sp = services.BuildServiceProvider()){IEnumerable<ITestService> ts1 = sp.GetServices<ITestService>();foreach (ITestService it in ts1){Console.WriteLine(it);}}Console.ReadLine();}}
}控制台输出:
Demo02.TestServiceImp1
Demo02.TestServiceImp2
Dispose...
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;namespace Demo02
{public interface ITestService{public string Name { get; set; }public void SayHi();}public class TestServiceImp1 : ITestService, IDisposable{public string Name { get; set; }public void Dispose(){Console.WriteLine("Dispose...");}public void SayHi(){Console.WriteLine($"Hi! I'm {Name}");}}public class TestServiceImp2 : ITestService{public string Name { get; set; }public void SayHi(){Console.WriteLine($"你好,我是{Name}");}}class Program{static void Main(string[] args){ServiceCollection services = new ServiceCollection();services.AddScoped<ITestService, TestServiceImp1>(); // 注册第一个services.AddScoped<ITestService, TestServiceImp2>(); // 注册第二个using (ServiceProvider sp = services.BuildServiceProvider()){var t1 = sp.GetService<ITestService>(); // 如果注册了多个,用Service方法那么获取最后一个。var t2 = sp.GetRequiredService<ITestService>(); // 如果注册了多个,用GetRequiredService方法那么获取的也是最后一个。Console.WriteLine(t1);Console.WriteLine(t2);}Console.ReadLine();}}
}控制台输出:
Demo02.TestServiceImp2
Demo02.TestServiceImp2

2. .NET依赖注入(视频Part-2-28)

  • 在这节课之前,我们讲的GetService等方法都是服务定位器的用法。从这节课开始,是真正的依赖注入。
2.1 依赖注入魅力渐显
  • 依赖注入是有传染性的,如果一个类的对象是通过DI创建的,那么这个类的构造函数中声明的所有服务类型的参数都会被DI赋值。
    • 但是如果一个对象是程序员手动创建的,那么这个对象就和DI没有关系,它的构造函数声明的服务类型参数就不会被自动赋值。
  • .NET的DI默认是构造函数注入。
    • 例如:编写一个类,连接数据库做插入操作,并且记录日志(模拟的输出),把Dao、日志都放入单独的服务类。
    • connstr见备注。
2.2 依赖注入示例
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;namespace Demo02
{class Controller{private readonly ILog log;private readonly IStorage storage;public Controller(ILog log, IStorage storage){this.log = log;this.storage = storage;}public void Test(){this.log.Log("开始上传");this.storage.Save("ABC", "1.txt");this.log.Log("上传完毕");}}interface ILog{public void Log(string msg);}class LogImpl : ILog{public void Log(string msg){Console.WriteLine($"日志:{msg}");}}interface IConfig{public string GetValue(string name);}class ConfigImpl : IConfig{public string GetValue(string name){return "Hello";}}interface IStorage{public void Save(string content, string name);}class StorageImpl : IStorage{private readonly IConfig config;public StorageImpl(IConfig config){this.config = config;}public void Save(string content, string name){string server = config.GetValue("server");Console.WriteLine($"向服务器{server}的文件名为{name}上传{content}");}}class Program{static void Main(string[] args){ServiceCollection services = new ServiceCollection();services.AddScoped<Controller>();services.AddScoped<ILog, LogImpl>();services.AddScoped<IStorage, StorageImpl>();services.AddScoped<IConfig, ConfigImpl>();using (var sp = services.BuildServiceProvider()){var c = sp.GetRequiredService<Controller>();c.Test();}Console.ReadLine();}}
}控制台输出:
日志:开始上传
向服务器Hello的文件名为1.txt上传ABC
日志:上传完毕说明:
1. 这样做的好处就是业务代码不用动,只需要配置新的服务即可。
2. DI可以降低模块之间的耦合。

结尾

书籍:ASP.NET Core技术内幕与项目实战

视频:https://www.bilibili.com/video/BV1pK41137He

著:杨中科

ISBN:978-7-115-58657-5

版次:第1版

发行:人民邮电出版社

※敬请购买正版书籍,侵删请联系85863947@qq.com※

※本文章为看书或查阅资料而总结的笔记,仅供参考,如有错误请留言指正,谢谢!※

相关新闻

  • 抖音批量视频下载工具源码C#源码|自动提取DY视频的软件工具
  • AI 检测:精准攻克米饭盒质检难题,赋能食品生产
  • 2025年9月北京中学集训随笔

最新新闻

  • 6个免费方法让你的手机视频秒变MP4 - 软件工具教程方法
  • Kali Linux实战:ARP欺骗攻击原理、环境搭建与Wireshark流量分析
  • 杭州靠谱品牌首饰回收排行,光谱验金透明称重全款现结 - 奢品小当家
  • 2026年安徽省合肥市合肥医药卫生学校招生简章官网发布:报名入口+报考指南 - cc江江
  • 武汉钻石回收怎么选?2026年实测合规机构名录 - 薛定谔的梨花猫
  • 机器学习模型上线后如何应对系统性风险与数据漂移

日新闻

  • 5分钟掌握Python进化算法:Geatpy高性能优化工具完全指南
  • Microchip 24AA044 EEPROM选型与应用全指南:从参数解析到实战编程
  • 华为的鸿蒙到底有多牛?为什么称作遥遥领先?

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号