NopCommerce4.7整个代码里面都贯彻了一个面向接口编程的思想。nopCommerce4.7商城系统提供了两种依赖注入的形成,可以自行选择。
因为最开始没有出现.net core的时候就是采用的autofac,自从升级为asp.net core后,框架默认提供了一个依赖注入容器。那么autofac和默认的依赖注入容器有什么区别呢?
一、UseDefaultServiceProvider 与autofac的区别
UseDefaultServiceProvider
是ASP.NET Core中的一个方法,用于设置默认的依赖注入容器。而Autofac是一个开源的轻量级依赖注入容器,用于.NET应用程序。
UseDefaultServiceProvider
和Autofac的主要区别如下:
- 功能和特性:
UseDefaultServiceProvider
提供了基本的依赖注入功能,而Autofac提供了更丰富的功能,如属性注入、多租户支持、AOP等。 - 配置方式:
UseDefaultServiceProvider
的配置相对简单,通常在Startup
类的ConfigureServices
方法中进行服务注册。而Autofac的配置更加灵活,可以通过代码、配置文件或混合方式进行注册。 - 适用场景:如果项目对依赖注入的需求比较简单,
UseDefaultServiceProvider
可能就足够了。但如果需要更高级的功能或更灵活的配置,Autofac可能更适合。
总的来说,UseDefaultServiceProvider
适合简单的依赖注入场景,而Autofac则提供了更强大和灵活的功能,适用于更复杂的应用程序。在选择使用哪种方式时,需要根据项目的具体需求和架构来决定。nop4.7默认是采用的autoc。
二、开启autofac的方法
我们可以看一下切换依赖注入容器代码,如下图:
配置文件在Nop.Web项目中的App_Data文件夹中的appsettings.json中,如下图:
我是从官方下载的源码,没有做过改动。默认就是true。
三、nop中依赖注入相关源码分析
今天我们就来分析一下里面的源码,学习一下Nop在依赖注入方面设计思想,希望在以后的架构设计中对你有启发和帮助。
下面是Nop依赖注入相关类图。
EngineContext、ServiceCollectionExtensions(扩展方法)、NopEngine、NopStartup
下面我们再来看看这些类的核心代码。
我们打开Nop.Web项目的所有的Controller源码,可以看到基本上都是通过构造函数引用抽象的接口。如BlogController的构造函数的参数类型都是某一个接口,如下图:
那我们要想看这些接口到底依赖的是哪一个真正的实现类呢?
在项目Nop.Web.Framework中有一个类NopStartup,其作用就是采用接口IServiceCollection相关的API进行依赖注入,我们只要打开这个类文件,搜索一个指定的接口,就可以找到它依赖的具体类。例如,我们想看到IBlogService接口是依赖哪一个实现,在这个类中搜索IBlogService,会找到BlogService类注册下面的代码:
services.AddScoped<IBlogService, BlogService>();
下面我们来看看Nop在网站启动是怎么调用这个NopStartup类呢?
在项目Nop.Web也就是前台的起始项目有一个文件Program里只有一个函数Main,这函数的意义这里就不用说了,我相信学过ASP.NET Core同学都知道它的作用,下面是这个函数的里面有一行关键代码:
//add services to the application and configure service provider
builder.Services.ConfigureApplicationServices(builder);
这个方法是类型IServiceCollection的扩展方法。
public static void ConfigureApplicationServices(this IServiceCollection services,
WebApplicationBuilder builder)
{
//add accessor to HttpContext
services.AddHttpContextAccessor();
//initialize plugins
var mvcCoreBuilder = services.AddMvcCore();
var pluginConfig = new PluginConfig();
builder.Configuration.GetSection(nameof(PluginConfig)).Bind(pluginConfig, options => options.BindNonPublicProperties = true);
mvcCoreBuilder.PartManager.InitializePlugins(pluginConfig);
//create engine and configure service provider
var engine = EngineContext.Create();
builder.Services.AddRateLimiter(options =>
{
var settings = Singleton<AppSettings>.Instance.Get<CommonConfig>();
options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(httpContext =>
RateLimitPartition.GetFixedWindowLimiter(
partitionKey: httpContext.User.Identity?.Name ?? httpContext.Request.Headers.Host.ToString(),
factory: partition => new FixedWindowRateLimiterOptions
{
AutoReplenishment = true,
PermitLimit = settings.PermitLimit,
QueueLimit = settings.QueueCount,
Window = TimeSpan.FromMinutes(1)
}));
options.RejectionStatusCode = settings.RejectionStatusCode;
});
engine.ConfigureServices(services, builder.Configuration);
}
关键代码就是:
//create engine and configure service provider
var engine = EngineContext.Create();
创建一个NopEngine的实例,同时作为单例。
再回到扩展方法的ConfigureApplicationServices方法:
上图中的最后一行就是真正开始注册依赖的代码。
箭头代码意思就是找到NopStartup的实例,然后执行其ConfigureServices方法。
所以,整个代码用链:
Nop.Web.Program(builder.Services.ConfigureApplicationServices(builder))
->EngineContext.Create():var engine = EngineContext.Create();
->engine.ConfigureServices(services, builder.Configuration);
->Nop.Web.Framework.Infrastructure.NopStartup.ConfigureServices(IServiceCollection services, IConfiguration configuration)