阅读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 是怎么 ...
随机推荐
- 数据管理工具Flux、Redux、Vuex的区别
目录 为什么要进行数据管理? 怎么有效地进行数据管理? 数据管理工具 1. Flux 2. Redux 3. Vuex 使用数据管理工具的场景 相关资料 主要讲解一下前端为什么需要进行数据管理,有效的 ...
- 如何在虚拟环境里运行spyder?如解决import tensorflow as tf 出现importError:no module named 'tensorflow'
问题描述:我们安装tensorflow时,通过activate tensorflow把tensorflow安装在虚拟环境里了,当我们在spyder里想要使用tensorflow时,就会发现如下图所以情 ...
- 移动IM开发指南1:如何进行技术选型
<移动IM开发指南>系列文章将会介绍一个IM APP的方方面面,包括技术选型.登陆优化等.此外,本文作者会结合他在网易云信多年iOS IM SDK开发的经验,深度分析实际开发中的各种常见问 ...
- Storm 学习之路(三)—— Storm单机版本环境搭建
1. 安装环境要求 you need to install Storm’s dependencies on Nimbus and the worker machines. These are: Jav ...
- 系统学习 Java IO (十六)----这么多类,应该用哪个?
目录:系统学习 Java IO---- 目录,概览 Java IO目的和功能 Java IO 包含 InputStream,OutputStream,Reader 和 Writer 类的许多子类. 原 ...
- Gradle +HanLP +SpringBoot 构建关键词提取,摘要提取 。入门篇
前段时间,领导要求出一个关键字提取的微服务,要求轻量级. 对于没写过微服务的一个小白来讲.有点赶鸭子上架,但是没办法,硬着头皮上也不能说不会啊. 首先了解下公司目前的架构体系,发现并不是分布式开发,只 ...
- Python笔记【3】_元组学习
#!/usr/bin/env/python #-*-coding:utf-8-*- #Author:LingChongShi #查看源码Ctrl+左键 ''' tuple:以圆括号“()”括起来,以“ ...
- SCUT 125 :笔芯回文(DP)
https://scut.online/p/125 125. 笔芯回文 题目描述 bxbx有一个长度一个字符串SS,bxbx可以对其进行若干次操作. 每次操作可以删掉一个长度为k(1 \leq k \ ...
- Codeforces 755D:PolandBall and Polygon(思维+线段树)
http://codeforces.com/problemset/problem/755/D 题意:给出一个n正多边形,还有k,一开始从1出发,向第 1 + k 个点连一条边,然后以此类推,直到走完 ...
- Salesforce Admin篇(二) Report
针对salesforce系统也好,针对其他的平台系统也好,对于business user的需求以及疑问,数据往往决定了答案.业务人员提出了某些疑问,管理员需要根据需求的分析转换成数据的分析及过滤从而反 ...