news 2026/5/2 2:01:52

.Net 中的 ActivatorUtilitiesConstructor 特性

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
.Net 中的 ActivatorUtilitiesConstructor 特性

.Net 中的 ActivatorUtilitiesConstructor 特性

[ActivatorUtilitiesConstructor]是 .NET 依赖注入中的一个特性,用于指导 Microsoft.Extensions.DependencyInjection(MSDI)在类型有多个构造函数时,选择哪个构造函数进行实例化。

主要用途

1.解决构造函数选择歧义

当一个类有多个构造函数时,MSDI 默认选择参数最多且都能从容器中解析的构造函数。但有时这会导致问题:

publicclassMyService{// 默认情况下,DI 会选择这个构造函数(参数最多)publicMyService(IService1s1,IService2s2,stringconfigValue){// configValue 无法从容器解析,会抛出异常!}// 实际上我们想用这个publicMyService(IService1s1,IService2s2){// 只有可解析的参数}}

2.明确指定构造函数

使用[ActivatorUtilitiesConstructor]明确告诉 DI 使用哪个:

publicclassMyService{publicMyService(IService1s1,IService2s2,stringconfigValue){// 这个不会被 DI 使用}[ActivatorUtilitiesConstructor]publicMyService(IService1s1,IService2s2){// DI 会优先使用这个构造函数}}

工作原理

  1. 标记优先级:标记的构造函数会被优先考虑
  2. 兼容性检查:只考虑标记的构造函数能否从容器解析所有参数
  3. 回退机制:如果标记的构造函数参数无法全部解析,会尝试其他构造函数

常见场景

场景1:有可选参数时

publicclassReportService{privatereadonlyILogger_logger;privatereadonlystring_format;publicReportService(ILogger<ReportService>logger){_logger=logger;_format="Default";}[ActivatorUtilitiesConstructor]publicReportService(ILogger<ReportService>logger,IOptions<ReportOptions>options){_logger=logger;_format=options.Value.Format;}}

场景2:第三方库扩展

// 扩展第三方库的类publicclassExtendedThirdPartyService:ThirdPartyService{// 第三方库可能没有无参构造函数publicExtendedThirdPartyService():base("default"){}[ActivatorUtilitiesConstructor]publicExtendedThirdPartyService(IConfigurationconfig):base(config.GetValue<string>("ApiKey")){}}

使用注意事项

1.仅用于ActivatorUtilities.CreateInstance

// 这个特性主要影响以下方法:varinstance=ActivatorUtilities.CreateInstance<MyService>(serviceProvider);varinstance=ActivatorUtilities.CreateInstance(serviceProvider,typeof(MyService));

2.与直接容器解析的区别

// 使用特性 - 受 [ActivatorUtilitiesConstructor] 影响services.AddTransient<MyService>();varservice=serviceProvider.GetService<MyService>();// 直接注册实例工厂 - 不使用该特性services.AddTransient(sp=>newMyService("hardcoded"));

3.多个标记会报错

publicclassBadExample{[ActivatorUtilitiesConstructor]publicBadExample(IService1s1){}[ActivatorUtilitiesConstructor]// ❌ 运行时错误:多个标记publicBadExample(IService2s2){}}

实际示例

publicclassPaymentProcessor{privatereadonlyIPaymentGateway_gateway;privatereadonlybool_useSandbox;// 用于测试或特定场景publicPaymentProcessor(IPaymentGatewaygateway){_gateway=gateway;_useSandbox=false;}// 生产环境使用 - 从配置读取[ActivatorUtilitiesConstructor]publicPaymentProcessor(IPaymentGatewaygateway,IConfigurationconfig){_gateway=gateway;_useSandbox=config.GetValue<bool>("Payment:UseSandbox");}}// 注册services.AddScoped<IPaymentGateway,StripeGateway>();services.AddScoped<PaymentProcessor>();// 使用时,DI 会自动选择带 [ActivatorUtilitiesConstructor] 的构造函数

替代方案

如果不想使用特性,也可以:

  1. 使用工厂方法注册
services.AddScoped(sp=>newMyService(sp.GetRequiredService<IService1>(),sp.GetRequiredService<IService2>()));
  1. 简化设计(推荐):尽量保持单个构造函数,使用 Options 模式处理配置。

总结

[ActivatorUtilitiesConstructor]是一个解决构造函数选择问题的工具,但在良好设计的应用中应该很少需要。优先考虑通过单一构造函数Options 模式来简化设计,这会使代码更清晰且易于测试。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/30 2:49:02

Open Code教程(四)| 高级配置与集成

Open Code教程&#xff08;四&#xff09;| 高级配置与集成OpenCode 高级配置与集成一、前言二、本地模型配置方式一&#xff1a;Ollama&#xff08;推荐&#xff09;方式二&#xff1a;LM Studio方式三&#xff1a;llama.cpp本地模型推荐三、AGENTS.md 配置创建方式推荐结构高…

作者头像 李华
网站建设 2026/5/1 8:50:08

django基于python的旅游个性化定制平台的设计与实现

目录摘要关于博主开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;摘要 随着旅游业的快速发展&#xff0c;个性化旅游定制需求日益增长。传统的旅游平台往往提供标准化产品&#xff0c;难以满…

作者头像 李华
网站建设 2026/4/29 22:40:05

厨房灵感不设限:cpolar内网穿透让 YunYouJun cook 从本地走向全网

YunYouJun/cook 的核心功能围绕 “随机菜谱推荐” 展开&#xff0c;用户可输入关键词&#xff08;如 “素食”“10 分钟完成”&#xff09;或筛选条件&#xff08;如烹饪难度、可用厨具&#xff09;&#xff0c;快速获取适配的菜谱方案&#xff0c;同时支持用户提交自己的私房菜…

作者头像 李华
网站建设 2026/5/1 9:47:00

深度学习毕设项目:基于python-CNN深度学习的水稻是否伏倒识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华