创建一个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类的目的。
  1. 接口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);
  1. nop使用Autofac作为注入框架,它是如何实现的
     var containerBuilder = new ContainerBuilder();
//register engine
containerBuilder.RegisterInstance(this).As<IEngine>().SingleInstance(); //create service provider
_serviceProvider = new AutofacServiceProvider(containerBuilder.Build()); return _serviceProvider;
  1. 接口IEngine的作用? 配置startup 服务和请求管道、autofac注册和解析
IServiceProvider ConfigureServices(IServiceCollection services, IConfiguration configuration);
void ConfigureRequestPipeline(IApplicationBuilder application);
T Resolve<T>() where T : class;
  1. 如何使用注入的服务?

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源码的更多相关文章

  1. daily news新闻阅读客户端应用源码(兼容iPhone和iPad)

    daily news新闻阅读客户端应用源码(兼容iPhone和iPad),也是一款兼容性较好的应用,可以支iphone和ipad的阅读阅读器源码,设计风格和排列效果很不错,现在做新闻资讯客户端的朋友可 ...

  2. 04、NetCore2.0下Web应用之Startup源码解析

    04.NetCore2.0Web应用之Startup源码解析   通过分析Asp.Net Core 2.0的Startup部分源码,来理解插件框架的运行机制,以及掌握Startup注册的最优姿势. - ...

  3. 如何阅读Android系统源码-收藏必备

    对于任何一个对Android开发感兴趣的人而言,对于android系统的学习必不可少.而学习系统最佳的方法就如linus所言:"RTFSC"(Read The Fucking So ...

  4. 教你阅读 Cpython 的源码(二)

    第二部分:Python解释器进程 在上节教你阅读 Cpython 的源码(一)中,我们从编写Python到执行代码的过程中看到Python语法和其内存管理机制. 在本节,我们将从代码层面去讨论 ,Py ...

  5. android新闻项目、饮食助手、下拉刷新、自定义View进度条、ReactNative阅读器等源码

    Android精选源码 Android仿照36Kr官方新闻项目课程源码 一个优雅美观的下拉刷新布局,众多样式可选 安卓版本的VegaScroll滚动布局 android物流详情的弹框 健身饮食记录助手 ...

  6. android选择器汇总、仿最美应用、通用课程表、卡片动画、智能厨房、阅读客户端等源码

    Android精选源码 android各种 选择器 汇总源码 高仿最美应用项目源码 android通用型课程表效果源码 android实现关键字变色 Android ViewPager卡片视差.拖拽及 ...

  7. android五子棋游戏、资讯阅读、大学课程表、地图拖拽检测、小说搜索阅读app等源码

    Android精选源码 Android 自动生成添加控件 android旋转动画.圆形进度条组合效果源码 一款很强的手机五子棋app源码 android地图拖拽区域检测效果源码 实现Android大学 ...

  8. android优化中国风应用、完整NBA客户端、动态积分效果、文件传输、小说阅读器等源码

    Android精选源码 android拖拽下拉关闭效果源码 一款优雅的中国风Android App源码 EasySignSeekBar一个漂亮而强大的自定义view15 android仿蘑菇街,蜜芽宝 ...

  9. 新手阅读 Nebula Graph 源码的姿势

    摘要:在本文中,我们将通过数据流快速学习 Nebula Graph,以用户在客户端输入一条 nGQL 语句 SHOW SPACES 为例,使用 GDB 追踪语句输入时 Nebula Graph 是怎么 ...

随机推荐

  1. 数据管理工具Flux、Redux、Vuex的区别

    目录 为什么要进行数据管理? 怎么有效地进行数据管理? 数据管理工具 1. Flux 2. Redux 3. Vuex 使用数据管理工具的场景 相关资料 主要讲解一下前端为什么需要进行数据管理,有效的 ...

  2. 如何在虚拟环境里运行spyder?如解决import tensorflow as tf 出现importError:no module named 'tensorflow'

    问题描述:我们安装tensorflow时,通过activate tensorflow把tensorflow安装在虚拟环境里了,当我们在spyder里想要使用tensorflow时,就会发现如下图所以情 ...

  3. 移动IM开发指南1:如何进行技术选型

    <移动IM开发指南>系列文章将会介绍一个IM APP的方方面面,包括技术选型.登陆优化等.此外,本文作者会结合他在网易云信多年iOS IM SDK开发的经验,深度分析实际开发中的各种常见问 ...

  4. Storm 学习之路(三)—— Storm单机版本环境搭建

    1. 安装环境要求 you need to install Storm’s dependencies on Nimbus and the worker machines. These are: Jav ...

  5. 系统学习 Java IO (十六)----这么多类,应该用哪个?

    目录:系统学习 Java IO---- 目录,概览 Java IO目的和功能 Java IO 包含 InputStream,OutputStream,Reader 和 Writer 类的许多子类. 原 ...

  6. Gradle +HanLP +SpringBoot 构建关键词提取,摘要提取 。入门篇

    前段时间,领导要求出一个关键字提取的微服务,要求轻量级. 对于没写过微服务的一个小白来讲.有点赶鸭子上架,但是没办法,硬着头皮上也不能说不会啊. 首先了解下公司目前的架构体系,发现并不是分布式开发,只 ...

  7. Python笔记【3】_元组学习

    #!/usr/bin/env/python #-*-coding:utf-8-*- #Author:LingChongShi #查看源码Ctrl+左键 ''' tuple:以圆括号“()”括起来,以“ ...

  8. SCUT 125 :笔芯回文(DP)

    https://scut.online/p/125 125. 笔芯回文 题目描述 bxbx有一个长度一个字符串SS,bxbx可以对其进行若干次操作. 每次操作可以删掉一个长度为k(1 \leq k \ ...

  9. Codeforces 755D:PolandBall and Polygon(思维+线段树)

    http://codeforces.com/problemset/problem/755/D 题意:给出一个n正多边形,还有k,一开始从1出发,向第 1 + k 个点连一条边,然后以此类推,直到走完 ...

  10. Salesforce Admin篇(二) Report

    针对salesforce系统也好,针对其他的平台系统也好,对于business user的需求以及疑问,数据往往决定了答案.业务人员提出了某些疑问,管理员需要根据需求的分析转换成数据的分析及过滤从而反 ...