阅读nopcommerce startup源码
创建一个asp.net core项目,可以到到startup类有两个方法
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
ConfigureServices方法:注册服务到容器中,在整个应用中都可以使用。推荐:自定义方法以Add开头 Configure方法:为应用配置请求管道.推荐:自定义方法以Use开头
这里并会深入的探讨依赖注入和IApplicationBuilder、IServiceCollection这些核心对象,这篇文章主要目的是快速的了解startup类和如何利用一些开源的项目(nopcommerce)去使用它。
nopcommerce是个优秀的开源的电商项目,应该都不会陌生,不管有没有项目中用到,但不妨碍我们去阅读学习他们优秀的地方。
一起先了解下项目结构 
- Nop.Core 核心层 :包含领域模型、和基础设施层(缓存、仓储接口、依赖注入、对象映射mapper等)、一些其他工具里的封装
- Nop.Data 数据层:orm与数据库的一些操作,仓储实现类,领域和表的映射等
- Nop.Services 应用服务层:业务服务操作
- Plugins 插件:nop 是插件式开发 ,扩展起来很是方便
- Nop.Web 表现层:ui交互
- Nop.Web.Framework:对asp.netcore mvc 进行一些扩展和封装
在回到今天的主角startup类 我进入Nop.Web项目 打开startup类
public class Startup
{
#region Fields
private readonly IConfiguration _configuration;
private readonly IHostingEnvironment _hostingEnvironment;
#endregion
#region Ctor
public Startup(IConfiguration configuration, IHostingEnvironment hostingEnvironment)
{
_configuration = configuration;
_hostingEnvironment = hostingEnvironment;
}
#endregion
/// <summary>
/// Add services to the application and configure service provider
/// </summary>
/// <param name="services">Collection of service descriptors</param>
public IServiceProvider ConfigureServices(IServiceCollection services)
{
return services.ConfigureApplicationServices(_configuration, _hostingEnvironment);
}
/// <summary>
/// Configure the application HTTP request pipeline
/// </summary>
/// <param name="application">Builder for configuring an application's request pipeline</param>
public void Configure(IApplicationBuilder application)
{
application.ConfigureRequestPipeline();
}
}
是不是很简洁,可以发现nop对IServiceCollection、IApplicationBuilder进行扩展了两个方法类 分别ServiceCollectionExtensions、ApplicationBuilderExtensions,下面我们分别快速的浏览这两个类的源码
我们F12进入ConfigureApplicationServices的实现方式一步一步的查看
var engine = EngineContext.Create(); //创建NopEngine
var serviceProvider = engine.ConfigureServices(services, configuration);
//find startup configurations provided by other assemblies
var typeFinder = new WebAppTypeFinder(); //反射工具类
var startupConfigurations = typeFinder.FindClassesOfType<INopStartup>();
//create and sort instances of startup configurations
var instances = startupConfigurations
.Select(startup => (INopStartup)Activator.CreateInstance(startup))
.OrderBy(startup => startup.Order);
////configure services
foreach (var instance in instances)
instance.ConfigureServices(services, configuration);
////register mapper configurations
//AddAutoMapper(services, typeFinder);
//register dependencies
RegisterDependencies(services, typeFinder);
protected virtual IServiceProvider RegisterDependencies(IServiceCollection services, ITypeFinder typeFinder)
{
var containerBuilder = new ContainerBuilder(); //Autofac
//register engine
containerBuilder.RegisterInstance(this).As<IEngine>().SingleInstance();
//register type finder
containerBuilder.RegisterInstance(typeFinder).As<ITypeFinder>().SingleInstance();
//populate Autofac container builder with the set of registered service descriptors
containerBuilder.Populate(services);
//find dependency registrars provided by other assemblies
var dependencyRegistrars = typeFinder.FindClassesOfType<IDependencyRegistrar>();
//create and sort instances of dependency registrars
var instances = dependencyRegistrars
.Select(dependencyRegistrar => (IDependencyRegistrar)Activator.CreateInstance(dependencyRegistrar))
.OrderBy(dependencyRegistrar => dependencyRegistrar.Order);
//register all provided dependencies
foreach (var dependencyRegistrar in instances)
dependencyRegistrar.Register(containerBuilder, typeFinder);
//create service provider
_serviceProvider = new AutofacServiceProvider(containerBuilder.Build());
return _serviceProvider;
}
F12进入ConfigureRequestPipeline
EngineContext.Current.ConfigureRequestPipeline(application);
public void ConfigureRequestPipeline(IApplicationBuilder application)
{
//find startup configurations provided by other assemblies
var typeFinder = Resolve<ITypeFinder>();
var startupConfigurations = typeFinder.FindClassesOfType<INopStartup>();
//create and sort instances of startup configurations
var instances = startupConfigurations
.Select(startup => (INopStartup)Activator.CreateInstance(startup))
.OrderBy(startup => startup.Order);
//configure request pipeline
foreach (var instance in instances)
instance.Configure(application);
}
到此这两个文件的源码已经过完了,觉得很核心的几个对象
- EngineContext: NopEngine的实例上下文 作用 获取创建和获取NopEngine的实例上下文的实例(涉及到的设计模式单例)
- IEngine、NopEngine: nop引擎还是很体贴的,里面封装了使用的方法如ioc 解析方法Resolve
- INopStartup :在应用程序启动时配置服务和中间件 当时我看过源码,有几处还是很巧妙的,下面我整理下,多个为什么,带着问题去看,印象更深刻,也达到了参考nop源码学习startup类的目的。
- 接口INopStartup作用? INopStartup有两个方法ConfigureServices,Configure 跟Startup方法作用都是一样的,nop把它抽离成接口的好处,可以很方便通过反射把实现INopStartup的类查找出来,然后掉用ConfigureServices,Configure方法
//find startup configurations provided by other assemblies
var typeFinder = new WebAppTypeFinder();
var startupConfigurations = typeFinder.FindClassesOfType<INopStartup>();
//create and sort instances of startup configurations
var instances = startupConfigurations
.Select(startup => (INopStartup)Activator.CreateInstance(startup))
.OrderBy(startup => startup.Order);
////configure services
foreach (var instance in instances)
instance.ConfigureServices(services, configuration);
//configure request pipeline
foreach (var instance in instances)
instance.Configure(application);
- nop使用Autofac作为注入框架,它是如何实现的
var containerBuilder = new ContainerBuilder();
//register engine
containerBuilder.RegisterInstance(this).As<IEngine>().SingleInstance();
//create service provider
_serviceProvider = new AutofacServiceProvider(containerBuilder.Build());
return _serviceProvider;
- 接口IEngine的作用? 配置startup 服务和请求管道、autofac注册和解析
IServiceProvider ConfigureServices(IServiceCollection services, IConfiguration configuration);
void ConfigureRequestPipeline(IApplicationBuilder application);
T Resolve<T>() where T : class;
- 如何使用注入的服务?
1.我们在Nop.Services项目中添加ProductService和ProductAttributeService两个业务服务
public class ProductService : IProductService
{
public string GetProductById(int productId)
{
return "获取产品";
}
}
public class ProductAttributeService: IProductAttributeService
{
public string GetProductAttributeById(int productAttributeId)
{
return "获取产品属性";
}
}
2.我们实现IDependencyRegistrar依赖注册接口
public class DependencyRegistrar : IDependencyRegistrar
{
/// <summary>
/// Register services and interfaces
/// </summary>
/// <param name="builder">Container builder</param>
/// <param name="typeFinder">Type finder</param>
public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder)
{
//file provider
builder.RegisterType<NopFileProvider>().As<INopFileProvider>().InstancePerLifetimeScope();
//data layer
//repositories
//services
builder.RegisterType<ProductAttributeService>().As<IProductAttributeService>().InstancePerLifetimeScope();
builder.RegisterType<ProductService>().As<IProductService>().InstancePerLifetimeScope();
}
/// <summary>
/// Gets order of this dependency registrar implementation
/// </summary>
public int Order => 0;
}
3.然后在homecontroller中测试,第一种构造函数注入,第二种直接使用IEngine的实例解析
#region fileds
private readonly IProductService productService;
#endregion
public HomeController(IProductService productService)
{
this.productService = productService;
}
public IActionResult Index()
{
//利用EngineContex进行解析
var productAttributeService = EngineContext.Current.Resolve<IProductAttributeService>();
ViewBag.result = this.productService.GetProductById(1);
ViewBag.result2 = productAttributeService.GetProductAttributeById(1);
return View();
}
然后运行查看效果

解析成功,展示的只是本分代码,实例代码上传到github上,喜欢的可以clone下来,自己调试调试,稍微调整下,放心用在自己的项目中,因为nop已经比较成熟了。
阅读nopcommerce startup源码的更多相关文章
- daily news新闻阅读客户端应用源码(兼容iPhone和iPad)
daily news新闻阅读客户端应用源码(兼容iPhone和iPad),也是一款兼容性较好的应用,可以支iphone和ipad的阅读阅读器源码,设计风格和排列效果很不错,现在做新闻资讯客户端的朋友可 ...
- 04、NetCore2.0下Web应用之Startup源码解析
04.NetCore2.0Web应用之Startup源码解析 通过分析Asp.Net Core 2.0的Startup部分源码,来理解插件框架的运行机制,以及掌握Startup注册的最优姿势. - ...
- 如何阅读Android系统源码-收藏必备
对于任何一个对Android开发感兴趣的人而言,对于android系统的学习必不可少.而学习系统最佳的方法就如linus所言:"RTFSC"(Read The Fucking So ...
- 教你阅读 Cpython 的源码(二)
第二部分:Python解释器进程 在上节教你阅读 Cpython 的源码(一)中,我们从编写Python到执行代码的过程中看到Python语法和其内存管理机制. 在本节,我们将从代码层面去讨论 ,Py ...
- android新闻项目、饮食助手、下拉刷新、自定义View进度条、ReactNative阅读器等源码
Android精选源码 Android仿照36Kr官方新闻项目课程源码 一个优雅美观的下拉刷新布局,众多样式可选 安卓版本的VegaScroll滚动布局 android物流详情的弹框 健身饮食记录助手 ...
- android选择器汇总、仿最美应用、通用课程表、卡片动画、智能厨房、阅读客户端等源码
Android精选源码 android各种 选择器 汇总源码 高仿最美应用项目源码 android通用型课程表效果源码 android实现关键字变色 Android ViewPager卡片视差.拖拽及 ...
- android五子棋游戏、资讯阅读、大学课程表、地图拖拽检测、小说搜索阅读app等源码
Android精选源码 Android 自动生成添加控件 android旋转动画.圆形进度条组合效果源码 一款很强的手机五子棋app源码 android地图拖拽区域检测效果源码 实现Android大学 ...
- android优化中国风应用、完整NBA客户端、动态积分效果、文件传输、小说阅读器等源码
Android精选源码 android拖拽下拉关闭效果源码 一款优雅的中国风Android App源码 EasySignSeekBar一个漂亮而强大的自定义view15 android仿蘑菇街,蜜芽宝 ...
- 新手阅读 Nebula Graph 源码的姿势
摘要:在本文中,我们将通过数据流快速学习 Nebula Graph,以用户在客户端输入一条 nGQL 语句 SHOW SPACES 为例,使用 GDB 追踪语句输入时 Nebula Graph 是怎么 ...
随机推荐
- 实战Java的反射机制
众所周知,Java要调用某个对象的方法首先需要对象实例化后才能调用. 而实例化对象常见的就是new执行和spring(DI)的依赖注入了. Spring的DI其实就是以反射作为最基础的技术手段. 一. ...
- ZooKeeper 系列(二)—— Zookeeper单机环境和集群环境搭建
一.单机环境搭建 1.1 下载 1.2 解压 1.3 配置环境变量 1.4 修改配置 1.5 启动 1. ...
- Flink UDF
本文会主要讲三种udf: ScalarFunction TableFunction AggregateFunction 用户自定义函数是非常重要的一个特征,因为他极大地扩展了查询的表达能力.本文除了介 ...
- memcached--add使用
memcached是一种管理内存的软件,来动态的分配机器的内存,将需要存储的数据以key-value(键值对)的形式存储在内存中. 1.memcached使用的存储算法是hash算法在内存中存储字符串 ...
- (数据科学学习手札62)详解seaborn中的kdeplot、rugplot、distplot与jointplot
一.简介 seaborn是Python中基于matplotlib的具有更多可视化功能和更优美绘图风格的绘图模块,当我们想要探索单个或一对数据分布上的特征时,可以使用到seaborn中内置的若干函数对数 ...
- BFS(三):双向广度优先搜索
所谓双向广度搜索指的是搜索沿两个方向同时进行:(1)正向搜索:从初始结点向目标结点方向搜索:(2)逆向搜索:从目标结点向初始结点方向搜索:当两个方向的搜索生成同一子结点时终止此搜索过程. 广度双向搜索 ...
- 2018.10.1 2018NOIP冲刺之立体图
2008NOIP普及组立体图 请自行百度(事实上放不下了) 图不是很清楚 下面有 [输入] 输入文件 drawing.in 第一行有用空格隔开的 2 个整数 m 和 n,表示有 m*n 个格子 (1 ...
- BZOJ 2039:[2009国家集训队]employ人员雇佣(最小割)
http://www.lydsy.com/JudgeOnline/problem.php?id=2039 题意:中文题意. 思路:一开始想着和之前做的最大权闭合图有点像,但是如果把边全部当成点的话,那 ...
- Vue技术点整理-Vue CLI
Vue CLI 是一个基于 Vue.js 进行项目快速开发的脚手架 注:具体安装步骤可参考Vue CLI,默认安装的脚手架,是没有service.util等工具类的,以下主要描述如何在脚手架的基础上进 ...
- 线性表的顺序存储C++代码实现
关于线性表的概念,等相关描述请参看<大话数据结构>第三章的内容, 1 概念 线性表list:零个或多个数据的有限序列. 可以这么理解:糖葫芦都吃过吧,它就相当于一个线性表,每个 ...