百度推广智能网站,企业网站建设合作合同,前端开发培训机构怎么样,躺平设计家官网依赖注入#xff08;Dependency Injection#xff0c;简称DI#xff09;是为了实现各个类之间的依赖的控制反转#xff08;Inversion of Control#xff0c;简称IoC #xff09;。 ASP.NET Core 中的Controller 和 Service 或者其他类都支持依赖注入。
依赖注入术语中Dependency Injection简称DI是为了实现各个类之间的依赖的控制反转Inversion of Control简称IoC 。 ASP.NET Core 中的Controller 和 Service 或者其他类都支持依赖注入。
依赖注入术语中 Service 是一个为其他对象提供服务的类**。 Service 不是一个Web Service与Web Service无关。
Service的使用方法一般是
在Main函数中注册Register到容器中可以使用ASP.NET Core 内置的容器或者第三方容器比如Autofac。在注册过的类的构造函数中即可将其他依赖类当作入参Resolve。或者通过IServiceScopeFactory 来Resolve。容器负责Dispose。
比如 定义接口
public interface IMyDependency
{void WriteMessage(string message);
}定义实现类
public class MyDependency : IMyDependency
{public void WriteMessage(string message){Console.WriteLine($MyDependency.WriteMessage Message: {message});}
}在Services容器中注册类
var builder WebApplication.CreateBuilder(args);
builder.Services.AddScopedIMyDependency, MyDependency();
builder.Services.AddScopedPageModel, IndexModel();
var app builder.Build();
app.Run();使用构造函数Resolve依赖对象
public class IndexModel : PageModel
{private readonly IMyDependency myDependency;public IndexModel(IMyDependency myDependency){myDependency myDependency; }
}这样不用在IndexModel 内部再new一个IMyDependency 类的对象而是使用构造函数传入的对象。 而由容器来维护创建Service的对象的生命周期这个过程叫做Resolve对象共有3种生命周期
Transient每次Resolve的时候都重新创建即使在同一个Http Reuest中。Scoped每次Http Reuest中Resolve的时候重新创建在该请求中不变。Singleton第一次Resolve的时候创建后续Resolve都使用相同的对象。Singleton 的Service必须线程安全因为所有线程都要用到并且要考虑内存的用量。 注意不应该在Singleton Service中Resolve Scoped类型的对象反过来可以因为可能导致Scoped类型的对象无法dispose。
使用IServiceScopeFactory 实现Resolve依赖对象
public class IndexModel : PageModel
{private readonly IServiceScopeFactory serviceScopeFactory;public IndexModel(IServiceScopeFactory serviceScopeFactory){serviceScopeFactory serviceScopeFactory; }public DoSomething(){using (var scope serviceScopeFactory .CreateScope()){// resolve a database connectionvar db scope.ServiceProvider.GetServiceIDatabaseConnection();// do something with it} }
}注册一组Service类似实现一个
builder.Host.UseSerilog();需要写一个ServiceCollection的扩展类然后在实现中注册相关的类
namespace Microsoft.Extensions.DependencyInjection
{public static class MyConfigServiceCollectionExtensions{public static IServiceCollection AddConfig(this IServiceCollection services, IConfiguration config){services.ConfigurePositionOptions(config.GetSection(PositionOptions.Position));services.ConfigureColorOptions(config.GetSection(ColorOptions.Color));return services;}public static IServiceCollection AddMyDependencyGroup(this IServiceCollection services){services.AddScopedIMyDependency, MyDependency();services.AddScopedIMyDependency2, MyDependency2();return services;}}
}然后就可以这样注册了
builder.Services.AddConfig(builder.Configuration).AddMyDependencyGroup();如何设计项目中的依赖Service
应当避免有状态的静态的类。应当避免地App中创建全局对象而应该使用singleton services。应当避免直接在service中初始化依赖的类这样会增加耦合。应当保证service功能单一以便测试。如果类中有大量的依赖注入说明这个类的功能过于复杂应当拆分使其单一职责。
Service的Dispose
Singleton类型的 Service 不应该添加Dispose方法App结束进程时会自动dispose。Scoped和Transient类型的Service 应该添加Dispose方法容器会自动调用。
其余建议
不支持 async/await 注入因为C#不支持async构造函数。不直接在容器中持久保存数据。配置项应该使用options pattern。不应该static访问service。尽量让DI工厂的操作同步快速。通在构造函数中注入的时候不应该使用 service locator pattern。配置service的时候不应该调用 BuildServiceProvider而只应该在注册B service时需要resolve A service的时候才用。开启Scope validation避免scoped service中使用singletons service。container 直接resolve service可能会导致内存泄露比如
static void TransientDisposablesWithoutDispose()
{var services new ServiceCollection();services.AddTransientExampleDisposable();ServiceProvider serviceProvider services.BuildServiceProvider();for (int i 0; i 1000; i){_ serviceProvider.GetRequiredServiceExampleDisposable();}//1,000 个对象会被创建serviceProvider 不dispose这1000个对象就不dispose。
}