网站建设关键词布局,centos 6.8 wordpress,广东网站建设的,网站在什么环境下做概述ASP.NET Core可以说是处处皆注入#xff0c;本文从基础角度理解一下原生DI容器#xff0c;及介绍下怎么使用并且如何替换官方提供的默认依赖注入容器。什么是依赖注入百度百科中对于依赖注入的定义#xff1a;控制反转#xff08;Inversion of Control#xff0c;缩写… 概述 ASP.NET Core可以说是处处皆注入本文从基础角度理解一下原生DI容器及介绍下怎么使用并且如何替换官方提供的默认依赖注入容器。什么是依赖注入 百度百科中对于依赖注入的定义控制反转Inversion of Control缩写为IoC是面向对象编程中的一种设计原则可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入Dependency Injection简称DI还有一种方式叫“依赖查找”Dependency Lookup。通过控制反转对象在被创建的时候由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说依赖被注入到对象中。依赖反转前那么在依赖反转之前或者叫控制反转之前直接依赖是怎么工作的呢这里ClassA直接依赖ClassB而ClassB又直接依赖ClassC任何一处的变动都会牵一发而动全身不符合软件工程的设计原则。依赖反转后应用依赖关系反转原则后A 可以调用 B 实现的抽象上的方法让 A 可以在运行时调用 B而 B 又在编译时依赖于 A 控制的接口因此典型的编译时依赖项发生反转 。 运行时程序执行的流程保持不变但接口引入意味着可以轻松插入这些接口的不同实现。依赖项反转是生成松散耦合应用程序的关键一环因为可以将实现详细信息编写为依赖并实现更高级别的抽象而不是相反 。 因此生成的应用程序的可测试性、模块化程度以及可维护性更高。 遵循依赖关系反转原则可实现依赖关系注入 。何谓容器 如果你用过Spring就知道其庞大而全能的生态圈正是因为有了它包含各种各样的容器来做各种事情其本质也是一个依赖反转工厂那么不知道你注意到没有控制反转后产生依赖注入这样的工作我们可以手动来做那么如果注入的服务成千上万呢那怎么玩呢那么问题来了控制反转了依赖的关系也交给了外部现在的问题就是依赖太多我们需要有一个地方来管理所有的依赖这就是容器的角色。 容器的主要职责有两个绑定服务与实例之间的关系控制生命周期。获取实例并对实例进行管理创建和销毁。ASP.NET Core里依赖注入是怎么实现的 在.Net Core里提供了默认的依赖注入容器IServiceCollection它是一个轻量级容器。核心组件为两个IServiceCollection和IServiceProviderIServiceCollection负责注册IServiceProvider负责提供实例。 使用两个核心组件前导入命名空间Microsoft.Extensions.DependencyInjection. 默认的ServiceCollection有以下三个方法IServiceCollection serviceCollectionnew ServiceCollection();
#三个方法都是注册实例只不过实例的生命周期不一样。
#单例模式只有一个实例
serviceCollection.AddSingletonILoginService, EFLoginService();
#每次请求都是同一个实例比如EntityFramework.Context
serviceCollection.AddScopedILoginService, EFLoginService();
#每次调用都是不同的实例
serviceCollection.AddTransientILoginService, EFLoginService();#接口声明
public interface IServiceCollection : IListServiceDescriptor, ICollectionServiceDescriptor, IEnumerableServiceDescriptor, IEnumerable
{
}#默认的ServiceCollection实际上是一个提供了ServiceDescriptor的List。
public class ServiceCollection : IServiceCollection, ICollectionServiceDescriptor, IEnumerableServiceDescriptor, IEnumerable, IListServiceDescriptor{private readonly ListServiceDescriptor _descriptors new ListServiceDescriptor();public int Count{get{return this._descriptors.Count;}}public bool IsReadOnly{get{return false;}}public ServiceDescriptor this[int index]{get{return this._descriptors[index];}set{this._descriptors[index] value;}}public void Clear(){this._descriptors.Clear();}public bool Contains(ServiceDescriptor item){return this._descriptors.Contains(item);}public void CopyTo(ServiceDescriptor[] array, int arrayIndex){this._descriptors.CopyTo(array, arrayIndex);}public bool Remove(ServiceDescriptor item){return this._descriptors.Remove(item);}public IEnumeratorServiceDescriptor GetEnumerator(){return (IEnumeratorServiceDescriptor) this._descriptors.GetEnumerator();}void ICollectionServiceDescriptor.Add(ServiceDescriptor item){this._descriptors.Add(item);}IEnumerator IEnumerable.GetEnumerator(){return (IEnumerator) this.GetEnumerator();}public int IndexOf(ServiceDescriptor item){return this._descriptors.IndexOf(item);}public void Insert(int index, ServiceDescriptor item){this._descriptors.Insert(index, item);}public void RemoveAt(int index){this._descriptors.RemoveAt(index);}}三个方法对应的生命周期值在枚举ServiceLifeTime中定义public enum ServiceLifetime
{Singleton,Scoped,Transient,
}三个方法确切来说是定义在扩展方法ServiceCollectionServiceExtensions中定义#这里我列出个别方法详细可参看源码
#导入Microsoft.Extensions.DependencyInjection
public static class ServiceCollectionServiceExtensions
{public static IServiceCollection AddTransient(this IServiceCollection services,Type serviceType,Type implementationType){if (services null)throw new ArgumentNullException(nameof (services));if (serviceType (Type) null)throw new ArgumentNullException(nameof (serviceType));if (implementationType (Type) null)throw new ArgumentNullException(nameof (implementationType));//这里注入时指定ServiceLifetime.Transientreturn ServiceCollectionServiceExtensions.Add(services, serviceType, implementationType, ServiceLifetime.Transient);}public static IServiceCollection AddScoped(this IServiceCollection services,Type serviceType,Type implementationType){if (services null)throw new ArgumentNullException(nameof (services));if (serviceType (Type) null)throw new ArgumentNullException(nameof (serviceType));if (implementationType (Type) null)throw new ArgumentNullException(nameof (implementationType));//这里注入时指定ServiceLifetime.Scopedreturn ServiceCollectionServiceExtensions.Add(services, serviceType, implementationType, ServiceLifetime.Scoped);}public static IServiceCollection AddSingleton(this IServiceCollection services,Type serviceType,Type implementationType){if (services null)throw new ArgumentNullException(nameof (services));if (serviceType (Type) null)throw new ArgumentNullException(nameof (serviceType));if (implementationType (Type) null)throw new ArgumentNullException(nameof (implementationType));//这里注入时指定ServiceLifetime.Singletonreturn ServiceCollectionServiceExtensions.Add(services, serviceType, implementationType, ServiceLifetime.Singleton);}
}ASP.NET Core里依赖注入是怎样运行的在Startup中初始化ASP.NET Core在Startup.ConfigureService中注入指定服务可以从方法参数IServiceCollection中看出这里还有个方法services.AddMvc(), 这个MVC框架本身自己注入的服务定义在MvcServiceCollectionExtesnsions类中。#Startup
public void ConfigureServices(IServiceCollection services)
{services.AddMvc();services.AddSingletonILoginService, EFLoginService();
}在构造函数中注入官方推荐在构造器中注入这里也是为了体现显示依赖。public class AccountController
{private ILoginService _loginService;public AccountController(ILoginService loginService){_loginService loginService;}
}如何替换其他容器 前面提到原生的依赖注入容器只是一个轻量级容器但是功能真的很有限比如属性注入、方法注入、子容器、lazy对象初始化支持。为何不好好借鉴一下Spring强大的背景呢所以这里我们用Autofac替换系统默认的依赖注入容器。先引用命名空间Autofac、Autofac.Extensions.DependencyInjection。我本机环境使用的.Net Core3.0。3.0不能修改直接修改Startup的ConfigureService方法了直接修改ConfigureService方法返回值会抛出异常ConfigureServices returning an System.IServiceProvider isnt supported. 这里可以参考Autofac文档已经有说明。修改Startup#直接声明方法ConfigureContainer
public class Startup{public Startup(IConfiguration configuration){Configuration configuration;}public IConfiguration Configuration { get; }public void ConfigureServices(IServiceCollection services){services.AddControllersWithViews();services.AddMvc();}public void ConfigureContainer(ContainerBuilder containerBuilder){containerBuilder.RegisterTypeEFLoginService().AsILoginService();}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}else{app.UseExceptionHandler(/Home/Error);app.UseHsts();}app.UseStaticFiles();app.UseRouting();app.UseAuthorization();app.UseEndpoints(endpoints {endpoints.MapControllerRoute(name: default,pattern: {controllerHome}/{actionIndex}/{id?});});}}修改Program#导入命名空间Autofac.Extensions.DependencyInjections,然后调用UseServiceProviderFactory
public class Program{public static void Main(string[] args){CreateHostBuilder(args).Build().Run();}public static IHostBuilder CreateHostBuilder(string[] args) Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder { webBuilder.UseStartupStartup(); }).UseServiceProviderFactory(new AutofacServiceProviderFactory());}参考链接https://docs.microsoft.com/zh-cn/dotnet/architecture/modern-web-apps-azure/architectural-principles#dependency-inversionhttps://www.cnblogs.com/loogn/p/10566510.htmlhttps://www.cnblogs.com/jesse2013/p/di-in-aspnetcore.html