创建一个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. linux 十五个原理知识点

    DNS系统架构与解析原理http协议通信原理TCP/IP的3次握手和四次断开原理MySQL主从同步原理Nginx配合php的fastcgi工作原理Lvs的4种模式工作原理Memcached工作原理(内 ...

  2. 不一样的go语言-玩转语法之二

      本文继续玩转语法,是为之二.   I/O(Input/Output),输入输出是计算机最为突出的特点,也可以说是计算机最为核心的功能.没有I/O,计算机就是一堆废铜废铁.从最低层的电子元器件开始, ...

  3. WebFlux 集成 Thymeleaf 、 Mongodb 实践 - Spring Boot(六)

    这是泥瓦匠的第105篇原创 文章工程: JDK 1.8 Maven 3.5.2 Spring Boot 2.1.3.RELEASE 工程名:springboot-webflux-5-thymeleaf ...

  4. Appcan 日期控件

    某个页面的onclick事件 <div id="topSendDate" class="ub ub-f1" onclick="appcan.wi ...

  5. python读取excel文件中所有sheet表格

    sales: store: """(1)用load_workbook函数打开excel文件,返回一个工作簿对象 (2)用工作簿对象获取所有的sheet (3)第一个for ...

  6. Jmh测试JDK,CGLIB,JAVASSIST动态代理方式的性能

    前言 JDK,CGLIB,JAVASSIST是常用的动态代理方式. JDK动态代理仅能对具有接口的类进行代理. CGLIB动态代理方式的目标类可以没有接口. Javassist是一个开源的分析.编辑和 ...

  7. django基础知识之自连接:

    自连接 对于地区信息,属于一对多关系,使用一张表,存储所有的信息 类似的表结构还应用于分类信息,可以实现无限级分类 新建模型AreaInfo,生成迁移 class AreaInfo(models.Mo ...

  8. Linux命令学习-ls命令

    Linux中,ls命令的全称是list,主要作用是列出当前目录下的清单. 列出Linux根目录下的所有目录 ls / 列出当前目录下所有文件夹和文件 ls 列出当前目录下所有文件夹和文件(包括以&qu ...

  9. kuangbin专题 专题一 简单搜索 Oil Deposits HDU - 1241

    题目链接:https://vjudge.net/problem/HDU-1241 题意:问有几个油田,一个油田由相邻的‘@’,组成. 思路:bfs,dfs都可以,只需要遍历地图,遇到‘@’,跑一遍搜索 ...

  10. 基于go语言结合微信小程序开发的微商城系统

    最近在慕课网上录制了一门<Golang微信小程序微商城系统原型>,这门免费课程特别适合在校大学生或者刚毕业的大学生,go语言初学者以及想要从事微商城开发项目入门的小伙伴们来学习.在课程当中 ...