博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET Core 2.1的配置、AOP、缓存、部署、ORM、进程守护、Nginx、Polly【源码】
阅读量:5341 次
发布时间:2019-06-15

本文共 26662 字,大约阅读时间需要 88 分钟。

ps:废话不多说。直接上代码:源码地址:

Configuration的配置

说明:基于三种方式的读取配置文件以及自定义读取自定义配置文件

文件结构

代码

PropertiesConfigurationProvider.cs

public class PropertiesConfigurationProvider:ConfigurationProvider{    string _path = string.Empty;    public PropertiesConfigurationProvider(string path)    {        this._path = path;    }    ///     /// 用于解析1.properties    ///     public override void Load()    {        var lines = File.ReadAllLines(this._path);        var dict = new Dictionary
(); foreach (var line in lines) { var items = line.Split('='); dict.Add(items[0], items[1]); } this.Data = dict; }}
View Code

PropertiesConfigurationSource.cs

public class PropertiesConfigurationSource : IConfigurationSource{    string _path = string.Empty;    public PropertiesConfigurationSource(string path)    {        this._path = path;    }    public IConfigurationProvider Build(IConfigurationBuilder builder)    {        return new PropertiesConfigurationProvider(_path);    }}
View Code

PropertiesConfigurationExtensions.cs

public static class PropertiesConfigurationExtensions{    public static IConfigurationBuilder AddPropertiesFile(this IConfigurationBuilder builder, string path)    {        builder.Add(new PropertiesConfigurationSource(path));        return builder;    }}
View Code

1.properties

port=8080host=127.0.0.1
View Code

appsettings.json

{  "mysql": {    "host": "127.0.0.1",    "port": 3306  },  "shopidlist": [    { "entid": 20 },    { "entid": 25 }  ]}
View Code

Program.cs

class Program{    static void Main(string[] args)    {        IConfiguration Configuration = new ConfigurationBuilder()            .SetBasePath(Environment.CurrentDirectory)            .AddJsonFile("appsettings.json", optional:true,reloadOnChange:true)            .AddPropertiesFile("1.properties")//加载自定义文件            .Build();        Appsettings appsettings = new Appsettings();        Configuration.Bind(appsettings);        Console.WriteLine(appsettings.mysql.port);        Console.WriteLine(Configuration["mysql:port"]);        Console.WriteLine(Configuration.GetValue
("mysql:port")); Console.WriteLine(Configuration.GetSection("mysql").GetSection("port").Value); //读取自定义文件 Console.WriteLine(Configuration["host"]); Console.Read(); }}public class Appsettings{ public Mysql mysql { get; set; } public Shopidlist[] shopidlist { get; set; }}public class Mysql{ public string host { get; set; } public int port { get; set; }}public class Shopidlist{ public int entid { get; set; }}
View Code

 

CollectionService注入

文件结构

 

代码

Program.cs

class Program{    static void Main(string[] args)    {        //IOC容器        ServiceCollection services = new ServiceCollection();        //注册服务        services.AddScoped
(); //注册日志服务 services.AddLogging(); var provider = services.BuildServiceProvider(); provider.GetService
().AddConsole(LogLevel.Debug); var fly = provider.GetService
(); fly.Flay(); }}public interface IFlay{ void Flay();}public class Pig : IFlay{ ILogger
logger = null; public Pig(ILoggerFactory loggerFactory) { logger=loggerFactory.CreateLogger
(); } public void Flay() { logger.LogInformation("这是Console日志"); Console.WriteLine("风口来了,猪都会飞了!"); }}
View Code

 

AOP AspectCore

文件结构

代码

Program.cs

//https://github.com/dotnetcore/AspectCore-Frameworkclass Program{    static void Main(string[] args)    {        ServiceCollection services = new ServiceCollection();        //注册AspectCore动态代理服务        services.AddDynamicProxy();        services.AddTransient
(); var provider= services.BuildDynamicProxyServiceProvider(); var mysql = provider.GetService
(); //走业务逻辑 var msg= mysql.GetData(10); Console.WriteLine(msg); //走缓存 msg = mysql.GetData(10); Console.WriteLine(msg); }}public class MysqlInterceptorAttribute : AbstractInterceptorAttribute{ private Dictionary
cacheDict = new Dictionary
(); public override Task Invoke(AspectContext context, AspectDelegate next) { //用id作为cachekey var cacheKey = string.Join(",", context.Parameters); if (cacheDict.ContainsKey(cacheKey)) { context.ReturnValue = cacheDict[cacheKey]; return Task.CompletedTask; } var task = next(context); //ReturnValue实际上就是一个传递值的媒介 var cacheValue = context.ReturnValue; cacheDict.Add(cacheKey, $"from Cache:{cacheValue.ToString()}"); return task; //Console.WriteLine("开始记录日志。。。。"); //var task = next(context); //Console.WriteLine("结束记录日志。。。。"); //return task; }}public interface IMySql{ [MysqlInterceptor] string GetData(int id);}public class MySql : IMySql{ public string GetData(int id) { var msg = $"已经获取到id={id}的数据"; //Console.WriteLine(msg); return msg; }}
View Code

 

MemoryCache

文件结构

代码

Program.cs

class Program{    static void Main(string[] args)    {        {
//cache的最大限度为100 MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions() { SizeLimit = 100 }); for (int i = 0; i < 1000; i++) { memoryCache.Set
(i.ToString(), i.ToString(), new MemoryCacheEntryOptions() { Size = 1 }); Console.WriteLine(memoryCache.Count); } } {
//被动过期,设置过期回调 MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions() { }); var cacheOptions = new MemoryCacheEntryOptions { AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(3),//3秒过期 }; cacheOptions.RegisterPostEvictionCallback((key, value, reason, obj) => { Console.WriteLine(reason); Console.WriteLine("执行过期回调"); }); memoryCache.Set("key", "value", cacheOptions); Console.WriteLine("3秒后过期将执行回调"); while (true) { Thread.Sleep(1000); Console.WriteLine(memoryCache.Get
("key")); } Console.ReadKey(); } {
//主动过期(10秒被动过期,2秒主动使用token让他过期) CancellationTokenSource tokenSource = new CancellationTokenSource(); MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions() { }); var cacheOptions = new MemoryCacheEntryOptions { AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10),//10秒过期 }; cacheOptions.AddExpirationToken(new CancellationChangeToken(tokenSource.Token));//加入Token cacheOptions.RegisterPostEvictionCallback((key, value, reason, obj) => { Console.WriteLine(reason); Console.WriteLine("执行过期回调"); }); memoryCache.Set("key", "value", cacheOptions); Console.WriteLine("10秒后过期将执行回调"); tokenSource.CancelAfter(TimeSpan.FromSeconds(2)); while (true) { Thread.Sleep(1000); Console.WriteLine(memoryCache.Get
("key")); } Console.ReadKey(); } }}
View Code

Redis MongoDB

文件结构

代码

Program.cs

class Program{    static void Main(string[] args)    {        //Redis        {            RedisCache redisCache = new RedisCache(new RedisCacheOptions()            {                Configuration = "127.0.0.1:6379",                InstanceName = "test"            });            //在Redis中是以Hash的模式存放的            redisCache.SetString("username", "jack", new DistributedCacheEntryOptions            {                AbsoluteExpiration = DateTime.Now.AddDays(1),            });            var info = redisCache.GetString("username");            Console.WriteLine(info);        }        //MongoDB        {            MongoDBCache mongoDBCache = new MongoDBCache(new MongoDBCacheOptions()            {                ConnectionString = "mongodb://127.0.0.1:27017",                DatabaseName = "mydb",                CollectionName = "mytest"            });            mongoDBCache.Set("username", Encoding.UTF8.GetBytes("jack"), new DistributedCacheEntryOptions {                AbsoluteExpiration = DateTime.Now.AddDays(1)            });            var info= Encoding.UTF8.GetString(mongoDBCache.Get("username"));            Console.WriteLine(info);        }    }}
View Code

Mysql.Data Dapper

文件结构

 

代码

class Program{    static void Main(string[] args)    {        //MySql.Data        {            var connectString = "server=127.0.0.1;por=3306;userid=root;pwd=123456;database=datamip;SslMode=none;";            //MySqlConnection mySqlConnection = new MySqlConnection(connectString);            //select            var ds = MySqlHelper.ExecuteDataset(connectString, "select * from users");            //select2            var reader = MySqlHelper.ExecuteReader(connectString, "select * from users");            var user = new Users();            while (reader.Read())            {                user.UserId = reader.GetInt32("UserID");                user.UserNick = reader.GetString("UserNick");                user.LoginIP = reader.GetString("LoginIP");                user.Email = reader.GetString("Email");            }            reader.Close();            //update            var result = MySqlHelper.ExecuteNonQuery(connectString, "update users set Email='786744873@qq.com' where UserID=1");        }        //Dapper        {            var connectString = "server=127.0.0.1;por=3306;userid=root;pwd=123456;database=datamip;SslMode=none;";            MySqlConnection mySqlConnection = new MySqlConnection(connectString);            //select            var userList = mySqlConnection.Query
("select * from users where UserID=@UserID",new { UserID=2 }); //update var nums = mySqlConnection.Execute("update users set Email='786744873@qq.com' where UserID=1"); } } class Users { public int UserId { get; set; } public string UserNick { get; set; } public string LoginIP { get; set; } public string Email { get; set; } }}
View Code

nohup supervisord部署Unbuntu

不得不说Ubuntu18.04版本是个巨坑。还是老老实实用16.04吧,错了,是VirtualBox是个巨坑,这wtf软件各种问题,浪费我几天时间,艹

文件结构

代码

ConfigurationManager.cs

public class ConfigurationManager{    public static IConfigurationRoot Configuration    {        get        {            var configuration = new ConfigurationBuilder()                .SetBasePath(Directory.GetCurrentDirectory())                .AddJsonFile(string.Format("appsettings.{0}.json", Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")),optional:true,reloadOnChange:true)                .AddJsonFile(string.Format("ops.{0}.json", Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")),optional:true,reloadOnChange:true)                .Build();            return configuration;        }    }}
View Code

Program.cs

class Program{    static void Main(string[] args)    {        var tokenSource = new CancellationTokenSource();        Task.Factory.StartNew(() =>        {            while (!tokenSource.IsCancellationRequested)            {                Console.WriteLine($"{DateTime.Now}:业务逻辑处理中");                Thread.Sleep(1000);            }        }).ContinueWith(t =>        {            Console.WriteLine("服务安全退出!");            Environment.Exit(0);//强制退出        });        Console.WriteLine("服务成功开启");        while (!"Y".Equals(ConfigurationManager.Configuration["isquit"],StringComparison.InvariantCultureIgnoreCase))        {            Thread.Sleep(1000);        }        tokenSource.Cancel();    }}
View Code

ops.Development.json  ||  ops.Production.json

{  "isquit": "N"}
View Code

部署过程

直接发布,发布以及虚拟机安装参照之前的博客:,这里主要讲如何进行持久化

ubuntu16.04开机提示:检测到系统程序出现问题

打开终端,输入 sudo gedit /etc/default/apport 把enabled=1改成enabled=0

方案一:nohub部署

先执行 nohup dotnet 程序集名称 & 

nohup dotnet ConsoleApp7.dll &  #(符号&使程序在后台运行) exit #(退出nohup模式)

然后输入 exit 进行退出,不然的话后台进程会被终结

启动后,会将程序运行输出记录在当前目录下的nohup.out文件下,如果当前目录不可写,则会被记录在Home目录下的nohup.out文件中

nohup dotnet ConsoleApp7.dll > my_nohup.log 2>&1 & #(将日志输出在my_nohup.log文件中,并将stderr重定向至stdout)

查看dotnet进程

ps -ef |grep dotnet

查看后10行nohup输出

tail /home/wyt/nohup.out

查看运行的后台进程

ps -ef | grep dotnet

停止程序

kill -9 12462 #(根据进程号关闭程序)

方案二:supervisord部署

安装

ubuntu安装: sudo apt-get install supervisor centos安装: yum install -y supervisor

安装成功后,会在 /etc/supervisor 目录下,生成 supervisord.conf 配置文件。

你也可以使用 echo_supervisord_conf > supervisord.conf 命令,生成默认的配置文件(不建议,内容比较多)。

 supervisord.conf 示例配置:

; supervisor config file[unix_http_server]file=/var/run/supervisor.sock   ; (the path to the socket file)chmod=0700                       ; sockef file mode (default 0700)[supervisord]logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log)pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)childlogdir=/var/log/supervisor            ; ('AUTO' child log dir, default $TEMP); the below section must remain in the config file for RPC; (supervisorctl/web interface) to work, additional interfaces may be; added by defining them in separate rpcinterface: sections[rpcinterface:supervisor]supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface[supervisorctl]serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL  for a unix socket; The [include] section can just contain the "files" setting.  This; setting can list multiple files (separated by whitespace or; newlines).  It can also contain wildcards.  The filenames are; interpreted as relative to this file.  Included files *cannot*; include files themselves.[include]files = /etc/supervisor/conf.d/*.conf
View Code

进程配置会读取 /etc/supervisor/conf.d 目录下的 *.conf 配置文件,我们在此目录下创建一个 ConsoleApp7.conf 进程配置文件:

[program:ConsoleApp7]directory=/data/outputcommand=/usr/bin/dotnet /data/output/ConsoleApp7.dllautostart=trueautorestart=truestartretries=10redirect_stderr=truestdout_logfile=/data/output/logs/out.logstderr_logfile=/data/output/logs/out.logenvironment=ASPNETCORE_ENVIRONMENT="Development"

需要注意的是,如果不是 root 账号,需要对这些目录进行权限设置,要不然会报一些错误(一定要在 root 账号下进行配置,要不然一系列权限引起的问题?)。

sudo chmod 777 /var/runsudo chmod 777 /etc/supervisor

接着就可以启动 Supervisord 了:

sudo supervisorctl reload sudo supervisord sudo supervisorctl ConsoleApp7

 supervisorctl  常用命令:

命令 说明
sudo supervisorctl stop program_name 停止某个进程
sudo supervisorctl start program_name 启动某个进程
sudo supervisorctl restart program_name 重启某个进程
sudo supervisorctl stop all 停止全部进程
sudo supervisorctl reload 载入最新的配置文件,停止原有进程并按新的配置启动、管理所有进程
sudo supervisorctl update 根据最新的配置文件,启动新配置或有改动的进程,配置没有改动的进程不会受影响而重启

运行成功后查看守护进程信息

sudo supervisorctl status all

使用NSSM进行Windows部署

是一款可将Nodejs项目注册为Windows系统服务的工具。当你的Node.js项目需要部署在Windows Server上时,NSSM是一个不错的选择。

使用

  1. 下载NSSM       .
  2. 根据自己的平台,将32/64位nssm.exe文件解压至任意文件夹。
  3. cmd定位至nssm.exe所在目录。
  4. 输入 nssm install {服务名称},即注册服务的名称。注册服务弹出如下NSSM界面。

Socket实现简单Web服务器

文件结构

代码

WebServer.cs

1     public class WebServer 2     { 3         static Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 4  5         public static void Start() 6         { 7             socket.Bind(new IPEndPoint(IPAddress.Any, 8200)); 8             socket.Listen(100); 9 10             //接收客户端的Socket请求11             socket.BeginAccept(OnAccept, socket);12 13             Console.WriteLine("当前Web服务器启动成功,端口号为8200");14         }15 16         //接收请求17         public static void OnAccept(IAsyncResult async)18         {19             var serverSocket = async.AsyncState as Socket;20 21             //获取到客户端的Socket22             var clientSocket = serverSocket.EndAccept(async);23 24             //进行下一步监听25             serverSocket.BeginAccept(OnAccept, socket);26 27             //获取其内容28             var bytes = new byte[10240];29             var len = clientSocket.Receive(bytes);30             var request = Encoding.UTF8.GetString(bytes, 0, len);31 32             var response = string.Empty;33 34             if (!string.IsNullOrEmpty(request)&&!request.Contains("favicon.ico"))35             {36                 //1.html37                 var filePath = request.Split("\r\n")[0].Split(" ")[1].Replace("/", "");38 39                 //获取文件内容40                 response = File.ReadAllText(filePath, Encoding.UTF8);41             }42 43             //按照Http响应码返回44             var responseHeader = string.Format(@"HTTP/1.1 200 OK45 Date: Tue, 11 Dec 2018 07:08:44 GMT46 Content-Type: text/html; charset=utf-847 Content-Length: {0}48 Connection: keep-alive49 Vary: Accept-Encoding50 Cache-Control: private, max-age=1051 Expires: Tue, 11 Dec 2018 07:08:54 GMT52 Last-Modified: Tue, 11 Dec 2018 07:08:44 GMT53 X-UA-Compatible: IE=1054 X-Frame-Options: SAMEORIGIN55 56 ", Encoding.UTF8.GetByteCount(response));57 58             //返回给客户端59             clientSocket.Send(Encoding.UTF8.GetBytes(responseHeader));60             clientSocket.Send(Encoding.UTF8.GetBytes(response));61 62             clientSocket.Close(); 63         }64 65     }
View Code

Program.cs

class Program{    static void Main(string[] args)    {        //浏览器访问127.0.0.1:8200/1.html        WebServer.Start();        Console.ReadKey();    }}
View Code

1.html

    

这是1.html的内容

View Code

2.html

    

这是2.html的内容

View Code

效果:

自定义Middleware

文件结构

代码

 MyStaticFileMiddleware.cs

public class MyStaticFileMiddleware{    private readonly RequestDelegate _next;    public MyStaticFileMiddleware(RequestDelegate next)    {        _next = next;    }    public Task Invoke(HttpContext context)    {        //1.logic   如果我当前的Context中有png,那么就直接从文件中读取,否则放下传递        var path = context.Request.Path.Value;        if (path.Contains(".png"))        {            var mypath = path.Trim('/');            return context.Response.SendFileAsync(mypath);        }        var task = _next(context);        return task;    }}
View Code

Nginx反向代理

安装

命令:

sudo apt-get install nginx

因为是首次安装 Nginx,通过运行以下命令显式启动

sudo service nginx start

在浏览器地址栏中输入类似于 http://192.168.XXX.XXX的IP地址或 http://域名就可以显示 Nginx 的默认登陆页了。

配置 Nginx

若要将 Nginx 配置为转发请求向 ASP.NET Core 应用程序的反向代理,修改  /etc/nginx/sites-available/default 。 在文本编辑器中打开它,并将内容替换为以下内容:

server {    listen        80;    server_name   test.com *.test.com;    location / {        proxy_pass         http://localhost:5000;        proxy_http_version 1.1;        proxy_set_header   Upgrade $http_upgrade;        proxy_set_header   Connection keep-alive;        proxy_set_header   Host $http_host;        proxy_cache_bypass $http_upgrade;    }}

Nginx 接受主机标头使用的端口 80 上的公共流量, Nginx 将匹配的请求转发到在 Kestrel http://localhost:5000

测试配置:

sudo nginx -t

显示结果如下所示:

nginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successful

重新加载配置:

sudo nginx -s reload

Polly

github地址:

使用

Install-Package Polly

代码

重试:RetryTest.cs

public class RetryTest{    //重试策略的设定    public static void Run()    {        var retrayPloicy = Policy.Handle
() .WaitAndRetry(new List
() { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(5) }, (ex, dt) => { Console.WriteLine($"{DateTime.Now} {ex.Message} {dt} "); }); int count = 0; var html = retrayPloicy.Execute(() => { var url = "http://1cnblogs.com"; if (count == 3) url = "http://cnblogs.com"; return GetHtml(url, ref count); }); //这个是我调用第三次获取到的内容。。 Console.WriteLine(html); } ///
/// 获取页面内容 /// ///
///
public static string GetHtml(string url, ref int count) { var html = string.Empty; try { var webClient = new WebClient(); html = webClient.DownloadString(url); } catch (Exception ex) { count++; throw; } return html; }}
View Code

熔断:CircuitBreakderTest.cs

public class CircuitBreakderTest{    public static void Run()    {        //如果当前连续有两个异常,那么触发熔断,10s内不能调用,10s之后重新调用。        //一旦调用成功了,熔断就解除了。        var policy = Policy.Handle
() .CircuitBreaker(2, TimeSpan.FromSeconds(10), (ex, timespan, context) => { //触发熔断 Console.WriteLine($"{DateTime.Now} 熔断触发:{timespan}"); }, (context) => { //恢复 Console.WriteLine($"{DateTime.Now} 熔断恢复"); }); var errCount = 1; for (int i = 0; i < 100; i++) { try { var msg = policy.Execute
((context, token) => { var url = "http://cnblogs1.com"; //模拟,当一定的时间后,恢复正常 if (errCount > 10) { url = "http://cnblogs.com"; } return GetHtml(url); }, new Dictionary
() { { i.ToString(), i.ToString() } }, CancellationToken.None); Console.WriteLine("logic:" + msg); } catch (Exception ex) { Console.WriteLine(string.Format("{0} 业务逻辑异常:'{1}'", DateTime.Now, ex.Message)); System.Threading.Thread.Sleep(2000); errCount++; } } } ///
/// 获取页面内容 /// ///
///
public static string GetHtml(string url) { var html = string.Empty; try { var webClient = new WebClient(); html = webClient.DownloadString(url).Substring(0, 10); } catch (Exception ex) { throw; } return html; }}
View Code

超时:TimeoutTest.cs

public class TimeoutTest{    public static void Run()    {        var cancellationToken = new CancellationToken();        //10s后 cancellationToken过期        var policy = Policy.Timeout(10);        //通过cancellationToken进行传值,如果10s过去,IsCancellationRequested 自动变成取消状态        policy.Execute((token) =>        {            for (int i = 0; i < 1000; i++)            {                //大家需要根据这个状态来做具体的业务逻辑                Console.WriteLine(token.IsCancellationRequested);                System.Threading.Thread.Sleep(1000);            }        }, cancellationToken);        Console.Read();    }    ///     /// 获取页面内容    ///     ///     /// 
public static string GetHtml(string url) { var html = string.Empty; Thread.Sleep(20); return html; }}
View Code

隔离:BulkheadTest.cs

public class BulkheadTest{    public static void Run()    {        var policy = Policy.Bulkhead(5, 1000);        Parallel.For(0, 100, (i) =>        {            //这里只能做一次调用            var result = policy.Execute
(() => { return GetHtml("http://cnblogs.com"); }); Console.WriteLine("已成功获取到数据:{0}", result); }); Console.Read(); } ///
/// 获取页面内容 /// ///
///
public static string GetHtml(string url) { var html = string.Empty; try { var webClient = new WebClient(); html = webClient.DownloadString(url); html = html.Substring(0, 17); Console.WriteLine($"当前线程ID={Thread.CurrentThread.ManagedThreadId}"); System.Threading.Thread.Sleep(2000); } catch (Exception ex) { throw; } return html; }}
View Code

回退:FallbackTest.cs

public class FallbackTest{    public static void Run()    {        var result = Policy
.Handle
() .Fallback(() => { return "接口失败,这个fake的值给你!"; }) .Execute(() => { return GetHtml("http://1cnblogs.com"); }); Console.WriteLine(result); Console.Read(); } ///
/// 获取页面内容 /// ///
///
public static string GetHtml(string url) { var html = string.Empty; try { var webClient = new WebClient(); html = webClient.DownloadString(url); } catch (Exception ex) { throw; } return html; }}
View Code

c#7.0

out语法

//out{    {
//old string val = "10"; int result; int.TryParse(val, out result); Console.WriteLine(result); } {
//new string val = "10"; int.TryParse(val, out int result); Console.WriteLine(result); }}
View Code

Tuple/ValueTuple

public static Tuple
GetData(){ return Tuple.Create(true, "操作成功");}public static (bool, string) GetDataNew(){ return (true, "操作成功");}//Tuple{ var tuple = GetData(); Console.WriteLine(tuple.Item1+" "+tuple.Item2); var (isSuccess, msg) = GetDataNew(); Console.WriteLine(isSuccess.ToString(),msg);}
View Code

Deconstruct(解构函数)

public class Person{    private string _name;    private int _age;    public Person(string name, int age)    {        this._name = name;        this._age = age;    }    public void Deconstruct(out string name, out int age)    {        name = this._name;        age = this._age;    }}//Deconstruct{    var (Name, Age) = new Person("jack", 18);    Console.WriteLine(Name + " " + Age);}
View Code

Local

//Local内部方法{    Console.WriteLine(GetLength("hello world"));    int GetLength(string str)    {        return str.Length;    }}
View Code

switch增强

//switch增强{    var list = new List() { 1, "2" };    foreach (var item in list)    {        switch (item)        {            //如果当前item是int类型,那么执行            case int val:                Console.WriteLine(val);                break;            //如果当前item是string类型,那么转成int            case string str when int.TryParse(str, out int ival):                Console.WriteLine(ival);                break;            default:                break;        }    }}
View Code

 

转载于:https://www.cnblogs.com/wyt007/p/10097160.html

你可能感兴趣的文章
自己也是一个21岁的大人了,需要有点责任感了
查看>>
let,const,var三者之间的区别
查看>>
nc+管道符的一种反弹shell姿势
查看>>
记一次Burpsuite安装SQLmap的sqlipy的小坑
查看>>
[Django学习]入门
查看>>
Stm32启动文件选择
查看>>
【汉诺塔问题】汉诺塔问题系列
查看>>
[转]Windows下Python多版本共存
查看>>
Java ExecutorService四种线程池的例子与说明(转发)
查看>>
邮件配置之spf word 发布
查看>>
40.编写简单的正则表达式
查看>>
SpringBoot修改Servlet相关配置
查看>>
ios命令行打IPA包(shenzhen)
查看>>
mini-css-extract-plugin 的用法(webpack4)
查看>>
DOM增删操作(select动态增加和删除以及清空)
查看>>
Javascript 回到顶部
查看>>
第一章 Shiro简介
查看>>
聚集函数------合计计算
查看>>
js 对象的深克隆
查看>>
输入URL 一瞬间发生了什么
查看>>