asp.net core 2.1 ioc 依赖注入


net core 中的依赖注入#

Package

Microsoft.Extensions.DependencyInjection

ServiceCollection 用来构造容器对象 IServiceProvider

调用 ServiceCollection 的 BuildServiceProvider() 创建 SerivceProvider, 可以获取 BuildServiceProvider() 之前 ServiceCollection 的对象

public class ServiceCollection : IServiceCollection, ICollection<ServiceDescriptor>, IEnumerable<ServiceDescriptor>, IEnumerable, IList<ServiceDescriptor>
{
    public ServiceCollection();

    public ServiceDescriptor this[int index] { get; set; }

    public int Count { get; }
    public bool IsReadOnly { get; }

    public void Clear();
    public bool Contains(ServiceDescriptor item);
    public void CopyTo(ServiceDescriptor[] array, int arrayIndex);
    public IEnumerator<ServiceDescriptor> GetEnumerator();
    public int IndexOf(ServiceDescriptor item);
    public void Insert(int index, ServiceDescriptor item);
    public void MakeReadOnly();
    public bool Remove(ServiceDescriptor item);
    public void RemoveAt(int index);
}

例子1:类的注入,一个简单的例子#

using Microsoft.Extensions.DependencyInjection;

ServiceCollection services = new ServiceCollection();
services.AddTransient<TestServiceImpl>();
using (ServiceProvider servicePorvider = services.BuildServiceProvider())
{
    TestServiceImpl testTemplpm = servicePorvider.GetService<TestServiceImpl>();
    testTemplpm.Name = "Tom";
    testTemplpm.SayHi();
}

public class TestServiceImpl
{
    public string Name { get; set; }
    public void SayHi()
    {
        Console.WriteLine($"Hi, I'm {Name}");
    }
}

ServiceProvider 实现了 IDisposable 接口, 所以需要用到 using.

例子2:接口注入#

using Microsoft.Extensions.DependencyInjection;

ServiceCollection services = new ServiceCollection();
services.AddTransient<ITestService, TestServiceImpl>();
using (ServiceProvider servicePorvider = services.BuildServiceProvider())
{
    var testTemplpm = servicePorvider.GetService<ITestService>();
    testTemplpm.Name = "Tom";
    testTemplpm.SayHi();
}


public interface ITestService
{
    public string Name { get; set; }
    public void SayHi();
}

public class TestServiceImpl : ITestService
{
    public string Name { get; set; }
    public void SayHi()
    {
        Console.WriteLine($"Hi, I'm {Name}");
    }
}

IServiceProvider 的服务器定位方法#

  1. GetService:此方法用于获取与给定类型匹配的第一个服务实例。如果容器中没有该类型的服务,它将返回null。因此,它被用于在没有明确要求的情况下获取可能存在的依赖项。

  2. GetRequiredService:此方法用于获取单一的,类型匹配的服务实例。如果容器中没有该类型的服务,它将抛出一个异常。因此,它被用于确保始终获得所需的依赖项。

  3. GetRequiredKeyedService:此方法用于获取与给定键关联的单一服务实例。如果容器中没有与该键匹配的服务,它将抛出一个异常。它被用于在有键的服务中获取所需的依赖项。

  4. GetServices:此方法用于获取与给定类型匹配的所有服务实例。如果容器中没有该类型的服务,它将返回一个空数组。因此,它被用于获取可能存在的依赖项集合。

生命周期#

内置的IOC有三种生命周期:
Transient: Transient服务在每次被请求时都会被创建。这种生命周期比较适用于轻量级的无状态服务。
Scoped: Scoped生命周期的服务是每次web请求被创建。
Singleton: Singleton生命能够周期服务在第一被请求时创建,在后续的每个请求都会使用同一个实例。如果你的应用需要单例服务,推荐的做法是交给服务容器来负责单例的创建和生命周期管理,而不是自己来走这些事情。

在Startup的ConfigureServices方法中

调用方法services.AddSingleton(typeof(IMyService),new MyService());
也可以services.AddSingleton(typeof(IMyService),typeof(MyService));
最好还是services.AddSingleton<IMyService, MyService>();

因为这样的话可以在MyService中通过构造函数注入其他服务。

注册程序集的所有类#

            //通过反射把所有服务接口进行了注入: 
            var serviceAsm = Assembly.Load(new AssemblyName("Service"));
            foreach (Type serviceType in serviceAsm.GetTypes()
            .Where(t => typeof(IServiceTag).IsAssignableFrom(t) && !t.GetTypeInfo().IsAbstract))
            {
                var interfaceTypes = serviceType.GetInterfaces();

                foreach (var interfaceType in interfaceTypes)
                {
                    services.AddSingleton(interfaceType, serviceType);
                }
            }

其他类注入#

在其他类怎么使用注入?假如在ExceptionFilter中想调用IUserService怎么办?要确保ExceptionFilter不是new出来的,而是IOC创建出来

services.AddSingleton<ExceptionFilter>(); 
//mvc core中注册filter要在AddMvc的回调方法中注册。
services.AddMvc(options =>
{
    var serviceProvider = services.BuildServiceProvider();
    var filter = serviceProvider.GetService<ExceptionFilter>();
    options.Filters.Add(filter);
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

手动获取注入#

在HttpContext可用的时候,也可以通过这种方法来解析服务:

 public IActionResult Index()
        {
         IMyDependency idService =  (IMyDependency)HttpContext.RequestServices.GetService(typeof(IMyDependency));
            return View();
        }

内置服务#

asp.net mvc core中架注入了很多服务:
https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1

最有用的就是IHostingEnvironment,其中主要成员有:WebRootPath属性(wwwroot文件夹的物理路径);ContentRootPath属性(网站根目录的物理路径)。
Microsoft.AspNetCore.Hosting下的HostingEnvironmentExtensions下还提供了一些扩展方法:
IsDevelopment()是否是开发环境、IsProduction()是否是生产环境。
asp.net mvc core中没有Server.MapPath()方法,根据你要定位的文件是不是在wwwroot下,你可以使用IHostingEnvironment. WebRootPath或者IHostingEnvironment. ContentRootPath来进行拼接。

    public class HomeController : Controller
    {
        private IHostingEnvironment iHostingEnvironment;

        public HomeController(IHostingEnvironment iHostingEnvironment)
        {
            this.iHostingEnvironment = iHostingEnvironment;
        }

        public IActionResult Index()
        {
            IHostingEnvironment host = new HostingEnvironment();
            host.WebRootPath = iHostingEnvironment.WebRootPath;
            host.ContentRootPath = iHostingEnvironment.ContentRootPath;
            host.ApplicationName = iHostingEnvironment.ApplicationName;
            host.EnvironmentName = iHostingEnvironment.EnvironmentName;

//            host.ContentRootFileProvider = iHostingEnvironment.ContentRootFileProvider;
//            host.WebRootFileProvider = iHostingEnvironment.WebRootFileProvider;

            return View(host);
        }
        ...
    }

指定要由 web 主机使用的环境#

Program.cs

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseEnvironment("Development") //指定要由 web 主机使用的环境。
                .UseStartup<Startup>();

作者:【唐】三三

出处:https://www.cnblogs.com/tangge/p/10050670.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   【唐】三三  阅读(1200)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2016-12-01 随笔目录【2016年12月1日整理中~】
2015-12-01 Jquery.Datatables 基本创建方法
2010-12-01 【2】CSS-块状元素与内联元素
2010-12-01 JS代码实现网【像滚动条之类的JS代码收集网站】
2010-12-01 实现JS标签切换效果【CSS图片切换】
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示