如何在.net6webapi中实现自动依赖注入
Posted SaoJian
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在.net6webapi中实现自动依赖注入相关的知识,希望对你有一定的参考价值。
IOC/DI
IOC(Inversion of Control)控制反转:控制反正是一种设计思想,旨在将程序中的控制权从程序员转移到了容器中。容器负责管理对象之间的依赖关系,使得对象不再直接依赖于其他对象,而是通过依赖注入的方式来获取所需的资源。
ID(Dependency Injection)依赖注入:他是IOC的具体实现方式之一,使用最为广泛,DI通过在运行时动态地将某个依赖关系抽象为独立的组件,提交到容器之中,需要使用时再由容器注入,提升组件重用的频率,为系统搭建一个灵活,可扩展的平台。
IOC/DI是一种设计模式,用于解耦组件之间的依赖关系。在传统的编程模式中,组件之间的依赖关系是硬编码在代码中的,这样会导致代码的耦合度很高,难以维护和发展。而IOC/DI模式则是通过将组件之间的依赖关系交给容器来管理,组件不再直接依赖其他组件,而是通过容器来获取所依赖的对象。这样可以使组件之间的依赖关系更加灵活,容器可以根据需要动态地创建和管理组件,从而实现更好的可维护性和可扩展性。
如何在.net6webapi中使用依赖注入?
首先我们定义一个服务接口及对应的实现
public interface ITestServices int return123();
public class TestServices : ITestServices public int return123() return 123;
然后我们在Program.cs注入服务实现
var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddTransient<ITestServices, TestServices>(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) app.UseSwagger(); app.UseSwaggerUI(); app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
值得注意的是依赖注入有三种生命周期
- 作用域(Scoped):在应用程序启动时创建,并在应用程序关闭时销毁。这种类型的服务实例会被容器管理,但是只会被当前请求使用。当请求结束时,该服务实例会被销毁。
- 单例(Singleton):在应用程序启动时创建,并在整个应用程序运行期间保持不变。这种类型的服务实例会被容器管理,并且可以被多个请求共享。
- 瞬时(Transient):在应用程序启动时创建,并在应用程序关闭时销毁。这种类型的服务实例不会被容器管理,也不会被其他服务引用。
最后在需要使用的控制器中构造函数注入就可以使用了
[Route("[controller]/[action]")] [ApiController] public class TestController : ControllerBase private readonly ITestServices _testServices; public TestController(ITestServices testServices) _testServices= testServices; [HttpGet] public int Get123() => _testServices.return123();
怎么实现自动注入?
依赖注入好归好,就是每个服务都得在Program.cs注入服务实现,一但服务多起来,麻烦不说,Program.cs中的代码更是会变得凌乱不堪,可能会有小伙伴说,可以开一个扩展函数单独做注入,但私以为,既然有一种方法可以一劳永逸,何乐而不为呢?
其实现便是利用.net的高级特性之一,反射
首先我们定义三个生命周期接口,其对应依赖注入的三种生命周期
//瞬时注入服务接口 public interface ITransient //作用域注入服务接口 public interface IScoped //单例注入服务接口 public interface ISingleton
然后我们定义自动注入的扩展方法,其为核心实现
public static IServiceCollection RegisterAllServices(this IServiceCollection services) //获取当前程序集 var entryAssembly = Assembly.GetEntryAssembly(); //获取所有类型 //!. null包容运算符,当你明确知道表达式的值不为null 使用!.(即null包容运算符)可以告知编译器这是预期行为,不应发出警告 //例: entryAssembly!.GetReferencedAssemblies() 正常 //entryAssembly.GetReferencedAssemblies() 编译器判断entryAssembly有可能为null,变量下方出现绿色波浪线警告 var types = entryAssembly!.GetReferencedAssemblies()//获取当前程序集所引用的外部程序集 .Select(Assembly.Load)//装载 .Concat(new List<Assembly>() entryAssembly )//与本程序集合并 .SelectMany(x => x.GetTypes())//获取所有类 .Distinct();//排重 //三种生命周期分别注册 Register<ITransient>(types, services.AddTransient, services.AddTransient); Register<IScoped>(types, services.AddScoped, services.AddScoped); Register<ISingleton>(types, services.AddSingleton, services.AddSingleton); return services; /// <summary> /// 根据服务标记的生命周期interface,不同生命周期注册到容器里面 /// </summary> /// <typeparam name="TLifetime">注册的生命周期</typeparam> /// <param name="types">集合类型</param> /// <param name="register">委托:成对注册</param> /// <param name="registerDirectly">委托:直接注册服务实现</param> private static void Register<TLifetime>(IEnumerable<Type> types, Func<Type, Type, IServiceCollection> register, Func<Type, IServiceCollection> registerDirectly) //找到所有标记了Tlifetime生命周期接口的实现类 var tImplements = types.Where(x => x.IsClass && !x.IsAbstract && x.GetInterfaces().Any(tinterface => tinterface == typeof(TLifetime))); //遍历,挨个以其他所有接口为key,当前实现为value注册到容器中 foreach (var t in tImplements) //获取除生命周期接口外的所有其他接口 var interfaces = t.GetInterfaces().Where(x => x != typeof(TLifetime)); if (interfaces.Any()) foreach (var i in interfaces) register(i, t); //有时需要直接注入实现类本身 registerDirectly(t);
其核心逻辑便是通过反射扫描程序集,当扫描到实现了我们定义的生命周期接口时,为其实现对应的生命周期注入。
注册这个服务
builder.Services.RegisterAllServices();
然后我们就可以通过继承生命周期接口来实现自动服务注入
public interface ITestServices int return123();
public class TestServices : ITestServices, ITransient public int return123() return 123;
接下来无需在Program.cs注入服务实现
调用成功。
自动注入代码参考自:【NetCore】依赖注入的一些理解与分享 - wosperry - 博客园 (cnblogs.com)
SpringBoot中实现依赖注入功能
本文转载自:https://blog.csdn.net/linzhiqiang0316/article/details/52639888
今天给大家介绍一下SpringBoot中是如何实现依赖注入的功能。
在以往Spring使用中,依赖注入一般都是通过在Spring的配置文件中添加bean方法实现的,相对于这个方式SpringBoot的实现方式就显得非常便捷了。SpringBoot的实现方式基本都是通过注解实现的。
下面来看一下具体案例,这里我编写了三个测试类用于测试依赖注入到底是否可以正确实现。
TestBiz接口:
package example.biz; public interface TestBiz { public String getTest(String str); }
TestBizImp接口实现类:
package example.biz.imp; import example.biz.TestBiz; import org.springframework.stereotype.Component; /** @Service用于标注业务层组件 @Controller用于标注控制层组件(如struts中的action) @Repository用于标注数据访问组件,即DAO组件 @Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。 */ @Component public class TestBizImp implements TestBiz { @Override public String getTest(String str) { return "Return value is:"+str; } }
这里可以看到上面给出了四个注解,这四个注解其实都可以实现注入的功能,可是他们的用途有所不同,最好要根据具体的业务来添加这些注解。
TestController类:
@Controller public class TestController { @Autowired private TestBiz testBiz; @RequestMapping("/getTest") @ResponseBody public String getTest(String str){ return testBiz.getTest(str); } }
这里需要再接口上面添加@Autowired 这个注解,这个注解的功能就是实现TestBiz的实例化操作,等同于Spring中bean操作。
做完这些之后就可以启动项目,测试依赖注入是否已经实现了。运行结果如下所示:
这样SpringBoot就已经实现依赖注入功能了,是不是比Spring的实现过程要简单的多啊!
以上是关于如何在.net6webapi中实现自动依赖注入的主要内容,如果未能解决你的问题,请参考以下文章
使用 Prism 在 Xamarin Forms 的后台服务中实现依赖注入
依赖注入在 dotnet core 中实现与使用:1 基本概念