7.1ASP.NET Core中的依赖注入

7.1ASP.NET Core中的依赖注入

ASP.Net中Program.cs文件中,第一行var builder = WebApplication.CreateBuilder(args)返回的类型为WebApplicationBuilder类型,在该类型中Services属性为IServiceCollection类型,也就是容器接口,一般把服务都注册到这个Service属性里面

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();//将项目中的控制器及相关的服务注册到容器中
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();//将Swagger相关服务注册到容器中
//当我们想注册服务的时候,主要把注册代码放到builder.Build()之前就可以
//注册代码的顺序不会影响程序运行的效果
var app = builder.Build();

因为控制器被AddControllers()方法注册到了容器中,所以控制器中可以使用依赖注入的方式,在构造函数中依赖注入其他的类

public class MyService1
{
	public IEnumerable<string> GetNames()
	{
		return new string[] { "Tom", "Zack", "Jack" };
	}
}
//如果在var app = builder.Build();之前使用builder.Services.AddScoped<MyService1>();就可以像下面这样来注入服务了
public class TestController : ControllerBase
{
	private readonly MyService1 myService1;
	public TestController(MyService1 myService1)//构造函数,注入MyService1
	{
		this.myService1 = myService1;
	}
    [HttpGet]
    public string Test()
    {
        var names = myService1.GetNames();
        return string.Join(",", names);
    }
}

低频率服务的另类注入方式

如果一个类中有多个操作方法,这些操作方法用到的服务都要使用构造函数来注入(所有的服务都得包含进来,不管用不用)。如果一个操作方法用到的服务特别耗费资源并且使用频率低,则可以在操作方法中通过参数注入的方式,实现在执行某个方法的时候才注入特定的服务。

public string Test([FromServices]MyService1 myService1, string name) //只有在调用Test的时候,才注入MyService1,且不需要在构造函数中有
{
	var names = myService1.GetNames();
	return string.Join(",", names) + ",hello:" + name;
}
//建议多数还是要才去构造函数的方式来注入
//[FromServices]只有控制器类的操作方法才能这样用

案例

一个解决方案中会包含多个项目,并且解决方案中会引用各个项目,每个项目都会用到很多被注入的服务,所以我们需要在解决方案中把设计到的服务都要注册进去,这样就会很麻烦。现在开发一个案例来简化这些操作。

//创建接口和类
public interface ImoduleInitializer
{
    public void Initialize(IServiceCollection services);
}

public static IServiceCollection RunModuleInitializers(this IServiceCollection services,IEnumerable<Assembly> assemblies)
{
    //扫描所有程序集中实现了IModuleInitializer的类
    foreach (var implType in assemblies.SelectMany(asm =>  asm.GetTypes()).Where(t=>!t.IsAbstract && typeof(IModuleInitializer).IsAssignableFrom(t))
    {
        //创建了ImoduleInitializer类
        var initializer = (IModuleInitializer?)Activator.CreateInstance(implType);
        initializer.Initialize(services);
    }
    return services;
}
  1. 首先创建一个类库项目,并创建接口IMyService
public interface IMyService
{
    void SayHello();
}
  1. 创建类库项目demo1,引用IMyService接口
public class CnService : IMyService
{
    public void SayHello()
    {
        Console.WriteLine("你好");
    }
}
  1. 在demo1项目中创建IModuleInitializer的实现类ModuleInitializer
class ModuleInitializer : IModuleInitializer
{
    public void Initialize(IServiceCollection services)
    {
        services.AddScoped<IMyService, CnService>();//将CnService注册为IMyService的实现服务
    }
}
  1. 创建控制台程序,添加对上面项目的引用
ServiceCollection services = new ServiceCollection();
var assemblies = ReflectionHelper.GetAllReferencedAssemblies();//获取用户的所有程序集,代码过长,没有在这里给出
services.RunModuleInitializers(assemblies);//扫描指定程序集中所有实现了IModuleInitializer的类,并调用Initialize方法
using var sp = services.BuildServiceProvider();
var items = sp.GetServices<IMyService>();
foreach(var item in items)
{
    item.SayHello();
}
//并没有注册CnService服务但是可以使用
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

步、步、为营

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值