创建一个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. git实战经验(很实用)

    推荐学习git很好的网站https://www.breakyizhan.com/git/216.html 以下内容,虽然编排不行,但是请认真的读下去,都是自己平时请自操作的,放心使用. 这是个人的gi ...

  2. IOS关于数据加密(主要为登录加密)想总结的

    首先上来就来说一下,IOS常见的几种加密算法  *哈希(散列)函数 : MD5.SHA  *对称加密算法:DES.3DES.AES  *非对称加密算法:RSA 一.哈希(散列)函数  1.MD5 MD ...

  3. Laravel --- artisan创建表以及填充表数据流程总结

    1.创建建表文件 php artisan make:migration create_comments_table 打开database/migrations/xxx_create_comments_ ...

  4. 【查虫日志】快速判断一副灰度图像中是否只有黑色和白色值(即是否为二值图像)过程中bool变量的是是非非。

    二值图像我们在图像处理过程中是经常遇到的,有的时候我们在进行一个算法处理前,需要判断下一副图像的数据是否符合二值图的需求,这个时候我们可以写个简单的函数来做个判断,比如我写了一个很简单的的代码如下: ...

  5. java多线程死锁

    进程(线程)同步的基本概念 进程之间的制约关系 1. 直接制约关系(进程同步) 这个关系主要源于进程合作,例如,有一个输入进程A通过单缓冲向进程B提供数据,当该缓冲空时,进程B因为不能获得所需数据而被 ...

  6. 长春理工大学第十四届程序设计竞赛(重现赛)F

    F. Successione di Fixoracci 题目链接:https://ac.nowcoder.com/acm/contest/912/F 题目: 动态规划(Dynamic programm ...

  7. .NET开发框架(四)-服务器IIS安装教程

    Windows Server 2012 R2 配置篇,包括服务器IIS安装.网络负载均衡器安装.ASP.NET Core 安装. 前三篇教程中,我们分享了框架的功能与视频演示介绍(文尾扫码 加入 框架 ...

  8. Codeforces Gym101518H:No Smoking, Please(最小割)

    题目链接 题意 给出一个n*m的酒店,每个点是一个房间,要将这个酒店的房间划分成为两块(一块无烟区,一块吸烟区),相邻的两个房间之间有一条带权边,权值代表空气锁的面积,如果把这条边给去掉,那么需要花费 ...

  9. MacBook强制清除gardle缓存

    背景:在日常的工作开发中,为了方便维护一般采用gardle+Nexus的模式管理jar包,但方便的同时也会存在一些问题 例如:test-1.0.3.jar  jar包提供方修改了一些问题上传到Nexu ...

  10. 判断List中是否含有某个实体bean

    注意:使用List.contains(Object object)方法判断ArrayList是否包含一个元素对象(针对于对象的属性值相同,但对象地址不同的情况),如果没有重写List的元素对象Obje ...