首页 > 其他分享 >在 Development 环境下依赖注入的行为可能有所不同

在 Development 环境下依赖注入的行为可能有所不同

时间:2025-01-05 23:11:39浏览次数:7  
标签:Development 依赖 Interface1 校验 报错 MockSerivce 有所不同

奇怪的问题

本周被一个奇怪的问题困扰了一天。事情的起因是这样的:在某个 PR 合并后,我拉了最新代码,但是在我本地F5调试始终报错。示例代码如下:

    public interface Interface1
    {
        void Method1();
    }

    public class MockSerivce
    {
        public MockSerivce(Interface1 interface1)
        {

        }
    }

builder.Services.AddSingleton<MockSerivce>();

报的错误呢也显而易见:

Unable to resolve service for type 'DevelopmentTest.Interface1' while attempting to activate 'DevelopmentTest.MockSerivce'

我们没有注册 Interface1 到 DI 容器里,那自然实例化 MockSerivce 的时候就找不到依赖了。
但是奇怪的是:我其他同事们都没有这个问题,他们在本地调试的时候都好好的,并不会报错。并且在这个分支编译后的代码在开发服务器上运行的都很完美。
这个就有点冲击到我了,难道是我电脑有问题,VS 有问题,还是我人品有问题?

寻找答案

当然了代码是不会骗人的,造成以上问题一定不是我人品问题而是代码的问题。
经过一番尝试,我发现这个问题跟系统运行在哪个环境有关系。只要我把 launchSettings.json 里的 ASPNETCORE_ENVIRONMENTDevelopment 改成别的什么值,那么一切都运行正常了。正巧在我们组其他同事都维护一个自己的 appestings.username.json 然后运行在这个环境之下,也就是说他们都不运行在 Development 下。这就是为啥只有我会报错的原因了。
事情到了这一步,那么我们很容易猜测: .NET DI 系统在 Development 下是有骚操作的。在 Development 下它会进行依赖分析,如果依赖关系有错误,那么直接会报错。但是在其他环境下就不会提交分析校验,只有在运行时真正尝试实例化对象的时候才会报错。
当然靠猜测总是不太靠谱,干脆翻翻代码吧。很快就找到了:

    internal static ServiceProviderOptions CreateDefaultServiceProviderOptions(HostBuilderContext context)
        {
            bool isDevelopment = context.HostingEnvironment.IsDevelopment();
            return new ServiceProviderOptions
            {
                ValidateScopes = isDevelopment,
                ValidateOnBuild = isDevelopment,
            };
        }

HostingHostBuilderExtensions 这个扩展类里很清楚的看到,只有在 Development 下 DefaultServiceProviderOptions 的 ValidateScopesValidateOnBuild 会被设置为 True。这就直接证明了上面的猜想。只有在 Development 下才会在启动的时候去校验依赖关系。

强制校验

既然找到了答案,那么让我们来试一下:强制开启依赖关系的校验。

var builder = WebApplication.CreateBuilder(args);

builder.Host.UseDefaultServiceProvider(op =>
{
    op.ValidateOnBuild = true;
    op.ValidateScopes = true;
});

代码如上在 Host 上调用 UseDefaultServiceProvider 扩展方法,指定 ValidateScopesValidateOnBuild 都为 True
再次运行我们的项目,这个时候不管是在 Development 还是 Production 还是别的任何环境下,都会报错了。

Unable to resolve service for type 'DevelopmentTest.Interface1' while attempting to activate 'DevelopmentTest.MockSerivce'

总结

通过以上我们可以发现 .NET 的 DI 系统,在 Development 环境下跟其他环境的行为是不同的。在 Development 下会提交进行依赖关系的校验,如果有问题会提前报错。所以我们调试的时候请尽量选择在 Development 下进行或者手动强制开启校验。这个问题很容易被忽视,至少我没在其他博文里见有人提到过。其实在微软的官方文档上是提到了,但也确实就是提了一嘴而已。
关于这个话题其实还没完,还有一个更有意思的问题:Captive dependency 可以聊一下。但是今天太晚了,改天吧。
参考:https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection#scope-validation

标签:Development,依赖,Interface1,校验,报错,MockSerivce,有所不同
From: https://www.cnblogs.com/kklldog/p/18654126/di-in-development

相关文章

  • Ubuntu 22.04 手动安装MySQL 5.7.41时依赖包libtinfo5失败
     在Ubuntu22.04安装MySQL5.7.41低版本时,需要安装依赖包libtinfo5,但偶尔会出现安装失败,可使用以下步骤解决此问题。 1、sudoaptinstallsoftware-properties-common2、sudoadd-apt-repository"debhttp://archive.ubuntu.com/ubuntu/jammymainuniverse"3、sudoa......
  • 在 Blazor 和 ASP.NET Core 中使用依赖注入和Scoped 服务实现数据共享方法详解
        依赖注入(DependencyInjection,简称DI)是一种设计模式,用于将对象的依赖关系从对象内部解耦出来,由外部容器进行管理和提供。在Blazor和ASP.NETCore中,DI是内置的核心功能,它通过服务生命周期(Transient、Scoped、Singleton)来管理依赖项。依赖注入(DependencyInj......
  • Miniconda如何快速创建Pipenv虚拟环境的依赖
    当开发人员A使用pipenv管理依赖,而开发人员B使用miniconda时,B可以通过以下步骤快速导入A的项目依赖:步骤1:确认Python版本首先,确保A和B使用的Python版本兼容。可以通过查看Pipfile中的python_version字段来确认。步骤2:导出依赖开发人员A可以使用以下命令将Pipfile.lock......
  • WPF依赖属性和附加属性
    https://blog.csdn.net/wang__junhappy/article/details/84848780  依赖属性以及附加属性依赖属性(DependencyProperty)1.概念依赖属性是一种可以自己没有值,并能通过使用Binding从数据源获得值的属性(通俗的讲,就是依赖在别的属性上)。依赖属性是为了解决普通属性因继承而带来......
  • 前端开发中依赖包有问题怎么办
    作者:京东保险屠永涛在前端开发中,如果你发现某个依赖包存在问题,可以考虑以下步骤来解决:一、简单方案1.检查问题来源:确认问题是否由依赖包引起,而不是你的代码或其他配置问题。查看错误信息、文档和相关的GitHubissue,可能已经有解决方案或临时解决办法。2.更新依赖:检......
  • ASP.NET Core技术研究-探秘依赖注入框架
    ASP.NETCore在底层内置了一个依赖注入框架,通过依赖注入的方式注册服务、提供服务。依赖注入不仅服务于ASP.NETCore自身,同时也是应用程序的服务提供者。毫不夸张的说,ASP.NETCore通过依赖注入实现了各种服务对象的注册和创建,同时也实现了面向抽象的编程模式和编程体验,提升了应用......
  • .NET Core 注入依赖
    .NETCore是一个现代化的、跨平台的框架,提供了构建高性能和可扩展应用程序的工具。依赖注入(DependencyInjection,DI)和中间件(Middleware)是.NETCore框架中两个核心的概念,它们在应用程序的架构中扮演着关键的角色。本文将详细探讨这两个概念,并展示如何在.NETCore应用程序中有......
  • .net6 WebApi 使用特性实现自动依赖注入
    首先搞三个特性类///<summary>///作用域///</summary>[AttributeUsage(AttributeTargets.Class)]publicclassDiScopedAttribute:Attribute{}///<summary>///单例///</summary>[AttributeUsage(AttributeTargets.Class)]publicclassDiSing......
  • SpringBoot依赖注入完成后执行方法
    引入注解@PostConstruct注解说明1、@PostConstruct是Java中的一个注解,用于标记那些在依赖注入完成后需要执行的方法。它是Java的标准注解之一,定义在javax.annotation.PostConstruct包中。这个注解主要用于执行一些初始化操作,比如创建或初始化对象的内部状态。2......
  • Vue是怎样依赖收集的?
    Vue的依赖收集是Vue实现响应式数据绑定的核心机制之一。在Vue中,当组件初始化时,Vue会对组件的data进行初始化,将普通的JavaScript对象转换成响应式对象。这个过程中,Vue会进行依赖收集,以便在数据发生变化时能够通知到所有依赖这个数据的地方。以下是Vue依赖收集的主要步骤和原理:De......