解析.NET依赖注入中工厂委托自动解析对象的实现原理
针对你提出的三个疑惑,结合给出的代码逐一解析:
1. type => sp.GetRequiredService(type)为何是Func<Type, object>类型?参数type的含义是什么?
Func<Type, object>是.NET内置的委托类型,定义为接收一个Type类型参数,返回object类型结果的方法签名。你看到的lambda表达式type => sp.GetRequiredService(type)完全符合这个签名:输入一个Type,输出从DI容器获取的对象实例,因此可以直接赋值给这个委托类型。- 参数
type代表你需要从DI容器中获取的服务类型,这里特指ViewModel的类型(比如HomeViewModel、MainViewModel)。当调用NavigateTo<T>()时,type就是typeof(T)的结果。
2. 如何通过type解析出对应的对象实例?
这依赖于Microsoft.Extensions.DependencyInjection的核心服务查找机制:
- 在App构造函数中,你已经通过
_services.AddSingleton<MainViewModel>()这类方法,把ViewModel类型注册到了DI容器的服务注册表中,容器会记录每个类型对应的实例(单例模式下)或创建逻辑。 - 当调用
sp.GetRequiredService(type)时,DI容器会:- 在内部注册表中查找与传入
type匹配的服务; - 如果是单例服务,直接返回已创建好的实例;如果是其他生命周期(Scoped/Transient),则按注册逻辑创建新实例;
- 如果找不到匹配的服务,直接抛出异常(这是
GetRequiredService和GetService的核心区别,后者会返回null)。
- 在内部注册表中查找与传入
3. 拆解整个代码的运行机制
把流程分成DI容器初始化和导航时的服务解析两个阶段来看:
阶段1:DI容器初始化(App构造函数)
- 注册单例ViewModel:
_services.AddSingleton<MainViewModel>()和_services.AddSingleton<HomeViewModel>(),DI容器会为这两个类型创建单例实例并存储。 - 注册
INavigationService:- 使用工厂委托
sp => new NavService(type => sp.GetRequiredService(type)),其中sp是DI容器构建后的IServiceProvider实例; - 这里把
sp.GetRequiredService包装成Func<Type, object>委托,传递给NavService的构造函数,让NavService拥有间接调用DI容器获取服务的能力,同时避免直接依赖DI容器本身。
- 使用工厂委托
阶段2:导航时的ViewModel解析(调用NavigateTo<T>())
- 当调用
NavigateTo<HomeViewModel>()时,方法内部通过typeof(T)获取HomeViewModel的Type对象; - 调用
factory.Invoke(type),也就是执行sp.GetRequiredService(typeof(HomeViewModel)); - DI容器根据
HomeViewModel类型,返回之前注册的单例实例; - 把获取到的ViewModel赋值给
CurrentView,触发OnPropertyChanged()通知UI更新,完成导航。
核心设计思路
这段代码通过委托实现了解耦:NavService不需要知道DI容器的具体实现,只需要通过Func<Type, object>委托就能获取ViewModel,同时复用了DI容器的生命周期管理(比如单例ViewModel的复用),符合依赖倒置原则。
内容的提问来源于stack exchange,提问作者Jess Chan
相关产品推荐
相关产品推荐

