.net core指南

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hjkl950217/article/details/79998058

.net core指南

目前本文档只针对.net core 2.0和netstandard2.0

.net core 程序运行模式

目前.net core只有两种模式:

1.控制台模式
2.asp.net core程序

从本质上来说,asp.net core也是控制台程序。是在基础控制台模式上引入了asp.net core的库,然后就配置成了web应用。运行起来还是一个控制台程序

.net core与netstandard的关系

.net core是针对库文件
netstandard是针对库文件的标准

目前开发中用的最多的是Microsoft.NETCore.App 也就是网上下载的.net core 2.0 SDK(用户电脑上对应的是运行时)。但是对开发库来说,会基于netstandard这样的标准来设计。.net core 2.0 SDK对应的就是netstandard 2.0这个标准。如果以后SDK更新到3.0 也需要对应的标准(可能是netstandard 3.0也不一定)。

这有什么用呢?主要是解决向下兼容的问题。比如现在开发项目时,会用到AutoMapper这个库,他在Nuget上是这样写明依赖的:
这里写图片描述

发现没有?可以同时在FrameWorknetstandard !!而且支持netstandard 1.1以上的版本(只是基于netstandard的会引入一些库,而基于FrameWork则框架都提供)。

如果你开发项目,图快。=>在VS创建项目时选择.Net Core里面的,会基于SDK创建
如果你开发项目,图依赖少,轻便。=>在VS创建项目时选择.Net Standard里面的,会基于Standard创建,然后手动慢慢用入你要的库。
如果你是开发库=>在VS创建项目时选择.Net Standard里面的,会基于Standard创建

扫描二维码关注公众号,回复: 3348854 查看本文章

asp.net core的两种运行模式

.net core都会在项目的Program.cs文件中的Main方法中启动。

        public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder( args )
            //指定Kestrel作为Web主机使用的服务器。
            .UseKestrel( )
            .UseIISIntegration()
            //指定Web主机使用的内容根目录。
            .UseContentRoot( Directory.GetCurrentDirectory( ) )
            //按环境加载应用配置文件
            .ConfigureAppConfiguration( ( hostingContext , config ) =>
            {
                var env = hostingContext.HostingEnvironment;
                config.AddJsonFile( "appsettings.json" , optional: false , reloadOnChange: true )
                      .AddJsonFile( $"appsettings.{env.EnvironmentName}.json" , optional: true , reloadOnChange: true );
                config.AddEnvironmentVariables( );
            } )
            //启动时-日志配置
            .ConfigureLogging( ( hostingContext , logging ) =>
            {
                logging.AddConfiguration( hostingContext.Configuration.GetSection( "Logging" ) );
                logging.AddConsole( );
                logging.AddDebug( );
            } )
            //指定Web主机使用的启动类型
            .UseStartup<Startup>( )
            //指定web主机绑定的地址与端口
            .UseUrls("http://*:8048")
            //构建一个web主机
            .Build( );

从上代码是我默认生成的项目解析给你看的,其中有2行代码是我后面加的(后面会讲这是干嘛):


            .UseIISIntegration()

            //指定web主机绑定的地址与端口
            .UseUrls("http://*:8048")

默认生成的长这样(以web api为例):

        public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .Build();

我贴这3段代码的目的主要是为了说这两个.

 .UseKestrel( )
 .UseIISIntegration()

第一个就是.net core**跨平台**的基础。他是基于libuv(一个跨平台异步 I/O 库),然后Kestrel 是基于这个库的一个 ASP.NET Core Web 服务器。只要.net core支持的平台,都会支持这个服务器。 支持的平台可以点这里查看.

而第二个就是传统的iis部署。我没有使用过,这里就不细说了。

目前运行模式就是这两种。

asp.net core 服务注册

在web项目中一般会生成一个Setup.cs文件(如果你不喜欢也可以自己搞一个,但一定要有里面说到的两个方法,且方法名不能变!)。在这里的ConfigureServices方法中注册与配置你需要的服务:

        public void ConfigureServices( IServiceCollection services )
        {
            //下两行代码只是为了演示,演示向中间件添加自定义过滤器
            //var userDefinedFilter = new xxxFilter( );
            //services.AddMvc( x => x.Filters.Add( userDefinedFilter ) );

            //添加MVC服务
            services.AddMvc( opt =>
                {
                    //配置缓存
                    opt.CacheProfiles.Add( "Default" , new CacheProfile( ) { Duration = 60 } );
                    opt.CacheProfiles.Add( 
                        "TemplateCache" ,
                        new CacheProfile( )
                        {
                            Duration = 12 * 3600 ,
                            VaryByHeader = "User-Agent"
                        } );
                } )
                .AddJsonOptions(opt =>
                {
                    //使用Newtonsoft.Json里的enum转换器
                    opt.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
                    //忽略空值
                    opt.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
                });


        }

这里只是列出了部分,如果你什么都不需要,你只需要这样:

        public void ConfigureServices( IServiceCollection services )
        {
            //添加MVC服务
            services.AddMvc();
         }

如果需要添加更多,在实际使用中慢慢加就行。一般来说,方法参数都会是services.

如果你看到需要注册服务,记得在这个方法中就行。

需要注意的是:通常情况下 services.AddMvc();services.AddMvcCore(/*...*/);这样注册MVC的代码,放在方法的最后一个执行位置(就是方法里面最后一行啦)。因为注册服务时,注册方法一般不会去调用其他服务,但有时会有一些服务依赖之前注册的服务(比如它自己从IConfiguration中读取配置),这时就会有先后顺序的问题

然后是另一个重要的方法Configure,它一般长这个样子:

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseMvc();
        }

这个方法是用来配置HTTP请求管道(请求流水线)的,这里的代码需要严格注意先后顺序!!!为什么呢? 就像自来水从河到你家里面需要经过很长的路,上面的app.UseMvc();就像你的水龙头一样,你必须得让水经过水厂、水管、加压器等等中间件才可以使用。如果你把app.UseMvc();放在这个方法的第一行,相当于直接把水龙头安装到水源上了。但我们知道没有处理的过的水是无法直接饮用的(原始请求就二进制流)。

这个我觉得主要是把请求相关的一些东西,从web方法中剥离出来。比如日志、权限检查、异常处理(比如处理下格式),这些东西可以以中间件的方式配置在app.UseMvc();之前,那么业务代码(Controllers及以下都是)就不需要知道这些东西。这样我们的业务开发就可以更加纯粹。

而中间件的方式更大的好处是它天生就是异步的!一个最简单的中间件长这样:

            //.net core服务器异步说明
            app.Use( async ( context , next ) =>
            {
                //进来时自己的操作
                await next.Invoke( );//调用下一个中间件
                //出去时自己的操作
            } );

而中间件的开发按规范来都是异步的:

    /// <summary>
    /// IP记录中间件
    /// </summary>
    public class RequestIPMiddleware
    {
        /// <summary>
        /// 下一个中间件委托
        /// </summary>
        private readonly RequestDelegate nextMiddleware;
        /// <summary>
        /// 日志记录器
        /// </summary>
        private readonly ILogger logger;

        public RequestIPMiddleware( RequestDelegate next , ILoggerFactory loggerFactory )
        {
            this.nextMiddleware = next ?? throw new ArgumentNullException( nameof( next ) );
            this.logger = loggerFactory.CreateLogger<RequestIPMiddleware>( );
        }

        /// <summary>
        /// 开始执行中间件逻辑
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task Invoke( HttpContext context )
        {
            //这个中间件就是为了记录IP

            //1.自己的操作
            string ipStr = context.Connection.RemoteIpAddress.ToString( );
            this.logger.LogInformation( "\r\nUser IP: " + ipStr + "\r\n");

            //2.调用下一个中间件
            await this.nextMiddleware.Invoke( context );

            //3.上面的代码执行后的后续工作
            if( context.Response.StatusCode == 204 )
            {
                string logStr = $"IP为:{ipStr}的客户端发送了一次无效查询请求";
                this.logger.LogWarning( LoggingEvents.GetRequest , logStr );
            }

            return;
        }

    }

所以.net core开发的web在吞吐量上会有极大提高就是这样。web中耗时最上的是在IO上的消耗。采用异步后,请求进到控制器开始,就会从珍贵的web主线程中离开,让web主线程专心搞接待工作。

IOC与DI

IOC是依赖注入,采用IOC的好处有很多,大家可以自己从网上搜索。而DI就是是IOC模式中提供服务的一个容器。本文章中所有的方法,只要参数是I开头的,都是通过DI获取实例的。

.net core自带DI容器,目前支持三种模式:

1.临时服务—-AddTransient方法
2.存在整个请求生命周期—AddScoped方法
3.单例—AddSingleton方法

注册方式是在Setup.cs类中的ConfigureServices方法中调用:

services.AddScoped<IEmailService , EmailDAL>( );

你也可以单独写一个方法,只要ConfigureServices方法中引用到就可以了。

通过IOC后,程序极大的解耦,灵活性大大提高。而在.net core中使用IOC就是这么简单。

PS:
1.IOC有多种注入方式,但推荐构造方法注入,显式写明依赖关系。
2. .net core中的DI也是通过服务注入的,如果你使用控制台,你可以这样使用:

            //创建配置
            IConfiguration config = new ConfigurationBuilder()
                .AddInMemoryCollection()//将配置文件的数据加载到内存中
                .SetBasePath( Directory.GetCurrentDirectory() )//设置配置文件所在目录
                .AddJsonFile( "appsettings.json" , optional: true , reloadOnChange: true )
                .Build(); //编译成对象

             //创建DI
             var di = new ServiceCollection()
                .AddOptions() //注入IOptions<T>,这样就可以在DI容器中获取IOptions<T>了
                //.Configure<NairOption>( config )//注入配置数据
                .AddSingleton<IConfiguration>( config )
               // .AddSingleton<INairFactory >(new NairFactory( config ) )//添加Nair的IOC关系
                .AddSingleton<INairFactory,NairFactory>()
                .BuildServiceProvider();//编译


            //获取Nair客户端
            var client = di.GetService<INairFactory>().GetNairClient();

asp.net core 配置

Framework中,web应用是通过web.config来配置的。但是在.net core中,配置主要由以下几个部分构成:

1.注册服务时的配置
2.在http请求管道中配置
3.通过配置文件

而配置文件也大多数是给配置服务使用的。具体使用可以网上搜索下,有很多。这里就不细说了。

PS:Setup.cs中有一个属性叫public IConfiguration Configuration { get; }这个IConfiguration是一个接口,读取好的配置都会放在这里。不过配置从那里读取的,都可以Configuration ["你的配置名"]这样读取,默认会取第一个(有时配置会重名)。

而里面放的是一堆配置提供者的实例,有一个配置提供者的接口,只要你实现了这个接口,你也可以向里面灌入你的配置。这就为从多个地方读取配置提供了可能。

.net core项目文件和记事本开发

在VS 2017上开发.net core项目时,可以这样操作:

这里写图片描述
这里写图片描述

直接对项目文件进行修改,然后就可以达到项目配置 修改项目的一些处理了。几乎你在VS上能点击的功能都能在这里通过代码配置,VS上修改项目后,它也会把修改写到个文件中。

有人用VS code或其他来开发.net core项目,秘密在这里。有时开发中不想打开VS,就直接通过修改文件+命令编译来搞定。

.net CLI工具

这里写图片描述
这里写图片描述

如图所示,.net core也可以通过命令行来进行一些操作,比如发布、编译、还原包等等。VS中你能完成的项目级别的功能,这里都可以通过命令行搞定。一手记事本+命令行操作,岂不美哉?
关于命令的使用,点击这里查看。

包管理

这里写图片描述

如图所示,以前在Framework中,包就只有一个,现在被拆分成了很多个。也就是上面说到的,你可以在NetStandard的基础上从0添加库来达到依赖最小的效果。

在以前的Framework中,更新版本非常容易导致项目出问题。但是在.net core中,你不用担心这个问题,我在开发还遇到过引用NetStandard 1.0级别的库呢。只要项目依赖中的库和对应的版本在Nuget上有,就完全不用担心。上面讲 .net core与netstandard的关系时也提到了这个。

只要你写对你要的版本,依赖的问题交给Nuget搞定~!

猜你喜欢

转载自blog.csdn.net/hjkl950217/article/details/79998058