翼度科技»论坛 编程开发 .net 查看内容

第三单元 扩展知识

4

主题

4

帖子

12

积分

新手上路

Rank: 1

积分
12
1. 扩展方法


 
扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 扩展方法是一种静态方法,但可以像扩展类型上的实例方法一样进行调用。 对于用 C#、F# 和 Visual Basic 编写的客户端代码,调用扩展方法与调用在类型中定义的方法没有明显区别。
最常见的扩展方法是 LINQ 标准查询运算符,它将查询功能添加到现有的 System.Collections.IEnumerableSystem.Collections.Generic.IEnumerable 类型。 若要使用标准查询运算符,请先使用 using System.Linq 指令将它们置于范围中。 然后,任何实现了 IEnumerable 的类型看起来都具有 GroupByOrderByAverage 等实例方法。 在 IEnumerable 类型的实例(如 ListArray)后键入“dot”时,可以在 IntelliSense 语句完成中看到这些附加方法。
 
OrderBy 示例

下面的示例演示如何对一个整数数组调用标准查询运算符 OrderBy 方法。 括号里面的表达式是一个 lambda 表达式。 很多标准查询运算符采用 Lambda 表达式作为参数,但这不是扩展方法的必要条件。 有关详细信息,请参阅 Lambda 表达式
  1. class ExtensionMethods2
  2. {
  3.     static void Main()
  4.     {
  5.         int[] ints = { 10, 45, 15, 39, 21, 26 };
  6.         var result = ints.OrderBy(g => g);
  7.         foreach (var i in result)
  8.         {
  9.             System.Console.Write(i + " ");
  10.         }
  11.     }
  12. }
  13. //Output: 10 15 21 26 39 45
复制代码
 
扩展方法被定义为静态方法,但它们是通过实例方法语法进行调用的。 它们的第一个参数指定方法操作的类型。 参数前面是修饰符。 仅当你使用 using 指令将命名空间显式导入到源代码中之后,扩展方法才位于范围中。
 
自定义扩展方法


  • 创建一个静态类
  • 创建一个静态方法,这个方法即是你的扩展方法
  • 方法中必须将你要扩展的类型通过参数传递进来
  • 在你需要扩展的参数类型前面加this
  1. namespace Utils; // 你的命名空间
  2. // 扩展方法的工具类,注意一定要写成static 静态类
  3. public static class ExtendUtils
  4. {
  5.     /**
  6.      * 1. 静态类下所有的方法都只能是static 方法
  7.      * 2. 把你需要扩展的类型前面加this
  8.      */
  9.     public static int ParseInt(this string str)
  10.     {
  11.         if (string.IsNullOrWhiteSpace(str))
  12.         {
  13.             return 0;
  14.         }
  15.         int result = 0;
  16.         if (!int.TryParse(str, out result))
  17.         {
  18.             return 0;
  19.         }
  20.         
  21.         return result;
  22.     }
复制代码
 
 
使用

  • 在你使用扩展方法之前,必须将扩展方法所在命名空间引用进来
  1. using System;
  2. using NUnit.Framework;
  3. using Utils; // 若要使用扩展方法,必须先将其所在命名空间引用进来
  4. namespace TestProject1;
  5. public class Tests
  6. {
  7.     [SetUp]
  8.     public void Setup()
  9.     {
  10.     }
  11.     [Test]
  12.     public void Test1()
  13.     {
  14.         string strNumber = "30";
  15.         Console.WriteLine(strNumber.ParseInt()); // 使用扩展方法
  16.     }
  17. }
复制代码
 
2. 特性

使用特性,可以有效地将元数据或声明性信息与代码(程序集、类型、方法、属性等)相关联。 将特性与程序实体相关联后,可以在运行时使用反射这项技术查询特性,常运用于AOP技术。
特性具有以下属性:

  • 特性向程序添加元数据。 元数据是程序中定义的类型的相关信息。 所有 .NET 程序集都包含一组指定的元数据,用于描述程序集中定义的类型和类型成员。 可以添加自定义特性来指定所需的其他任何信息。 有关详细信息,请参阅创建自定义特性 (C#)
  • 可以将一个或多个特性应用于整个程序集、模块或较小的程序元素(如类和属性)。
  • 特性可以像方法和属性一样接受自变量。
  • 程序可使用反射来检查自己的元数据或其他程序中的元数据。 有关详细信息,请参阅使用反射访问特性 (C#)
 
创建自定义特性

可通过定义特性类创建自己的自定义特性,特性类是直接或间接派生自 Attribute 的类,可快速轻松地识别元数据中的特性定义。 假设希望使用编写类型的程序员的姓名来标记该类型。 可能需要定义一个自定义 Author 特性类:
  1. [System.AttributeUsage(System.AttributeTargets.Class |  
  2.                        System.AttributeTargets.Struct)  
  3. ]  
  4. public class AuthorAttribute : System.Attribute  
  5. {  
  6.     private string name;  
  7.     public double version;  
  8.   
  9.     public AuthorAttribute(string name)  
  10.     {  
  11.         this.name = name;  
  12.         version = 1.0;  
  13.     }  
  14. }  
复制代码
 
类名 AuthorAttribute 是该特性的名称,即 Author 加上 Attribute 后缀。 由于该类派生自 System.Attribute,因此它是一个自定义特性类。 构造函数的参数是自定义特性的位置参数。 在此示例中,name 是位置参数。 所有公共读写字段或属性都是命名参数。 在本例中,version 是唯一的命名参数。 请注意,使用 AttributeUsage 特性可使 Author 特性仅对类和 struct 声明有效。
可按如下方式使用这一新特性:
  1. [Author("P. Ackerman", version = 1.1)]  
  2. class SampleClass  
  3. {  
  4.     // P. Ackerman's code goes here...  
  5. }  
  6. AttributeUsage 有一个命名参数 AllowMultiple,通过此命名参数可一次或多次使用自定义特性。 下面的代码示例创建了一个多用特性。
  7. [System.AttributeUsage(System.AttributeTargets.Class |  
  8.                        System.AttributeTargets.Struct,  
  9.                        AllowMultiple = true)  // multiuse attribute  
  10. ]  
  11. public class AuthorAttribute : System.Attribute  
复制代码
 
在下面的代码示例中,某个类应用了同一类型的多个特性。
  1. [Author("P. Ackerman", version = 1.1)]  
  2. [Author("R. Koch", version = 1.2)]  
  3. class SampleClass  
  4. {  
  5.     // P. Ackerman's code goes here...  
  6.     // R. Koch's code goes here...  
  7. }  
复制代码
3. JSON 操作

JSON: JavaScript Object Notation(JavaScript 对象表示法)
JSON 是存储和交换文本信息的语法,类似 XML。
JSON 比 XML 更小、更快,更易解析。
1. 什么是Json


  • SON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
  • JSON 是轻量级的文本数据交换格式
  • JSON 独立于语言:JSON 使用 Javascript语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。 目前非常多的动态(PHP,JSP,.NET)编程语言都支持JSON。
  • JSON 具有自我描述性,更易理解
  1. {
  2.     "sites": [
  3.     {id:1, "name":"C#教程" , "url":"www.runoob.com" },
  4.     {id:2, "name":"google" , "url":"www.google.com" },
  5.     {id:3, "name":"微博" , "url":"www.weibo.com" }
  6.     ]
  7. }
复制代码
 
大家平时在自己写JSON时,可以借助于 在线JSON校验格式化工具(Be JSON)
  1. {
  2.     "sites": [
  3.         {
  4.             "name": "菜鸟教程",
  5.             "url": "www.runoob.com"
  6.         },
  7.         {
  8.             "name": "google",
  9.             "url": "www.google.com"
  10.         },
  11.         {
  12.             "name": "微博",
  13.             "url": "www.weibo.com"
  14.         }
  15.     ]
  16. }
复制代码
JSON 语法规则


  • 数据在键值对中
  • 数据由逗号分隔
  • 花括号保存对象
  • 方括号保存数组
     
JSON 名称/值对

JSON 数据的书写格式是:名称/值对。
名称/值对组合中的名称写在前面(在双引号中),值对写在后面(同样在双引号中),中间
用冒号隔开:"firstName":"John"
 
JSON 值可以是:

数字(整数或浮点数)
字符串(在双引号中)
逻辑值(
true 或 false)
数组(在方括号中)
对象(在花括号中)
null
JSON数据结构

json简单说就是javascript中的对象和数组,所以这两种结构就是对象和数组两种结构,通
过这两种结构可以表示各种复杂的结构
1、对象:对象在js中表示为“{}”括起来的内容,数据结构为 {key:value,key:
value,...}的键值对的结构,在面向对象的语言中,key为对象的属性,value为对应的属性
值,所以很容易理解,取值方法为 对象.key (
c# 对象[key])获取属性值,这个属性值的
类型可以是 数字、字符串、数组、对象几种。
2、数组:数组在js中是中括号“[]”括起来的内容,数据结构为
["java","javascript","vb",...],取值方式和所有语言中一样,使用索引获取,字段值的
类型可以是 数字、字符串、数组、对象几种。
经过对象、数组2种结构就可以组合成复杂的数据结构了。
.Net 中提供的JSON解析组件


  • Newtonsoft.Json
  • fastjson
 
2. 序列化与反序列化

使用nuget 工具 将 Newtonsoft.Json 引用到当前项目中
序列化

对象转换为Json
  1. using Newtonsoft.Json;
  2. public class Site
  3. {
  4.     public int Id { get; set; }
  5.     public string Name { get; set; }
  6.     public string Url { get; set; }
  7. }
  8. // 对象转换为Json
  9. [Test]
  10. public void ObjectToJson()
  11. {
  12.     Site site = new()
  13.     {
  14.         Id = 1,
  15.         Name = "任我行网络教育有限公司",
  16.         Url = "www.renwoxing.com"
  17.     };
  18.     string json = JsonConvert.SerializeObject(site);
  19.     Console.WriteLine(json);
  20. }
  21. // 输出结果
  22. {"Id":1,"Name":"任我行网络教育有限公司","Url":"www.renwoxing.com"}
复制代码
 
集合序列化
  1. [Test]
  2. public void ListToJson()
  3. {
  4.     List<Site> sites = new List<Site>();
  5.     sites.Add(new()
  6.               {
  7.                   Id = 1,
  8.                   Name = "任我行网络教育有限公司",
  9.                   Url = "www.renwoxing.com"
  10.               });
  11.     sites.Add(new()
  12.               {
  13.                   Id = 2,
  14.                   Name = "百度",
  15.                   Url = "www.baidu.com"
  16.               });
  17.     string json = JsonConvert.SerializeObject(sites);
  18.     Console.WriteLine(json);
  19. }
复制代码
 
输出结果:
  1. [{
  2.     "Id": 1,
  3.     "Name": "任我行网络教育有限公司",
  4.     "Url": "www.renwoxing.com"
  5. }, {
  6.     "Id": 2,
  7.     "Name": "百度",
  8.     "Url": "www.baidu.com"
  9. }]
复制代码
反序列化

json转对象
  1. [Test]
  2. public void JsonToObject()
  3. {
  4.     string json = "{"Id":1,"Name":"任我行网络教育有限公司","Url":"www.renwoxing.com"}";
  5.     Site site = JsonConvert.DeserializeObject<Site>(json);
  6. }
复制代码
 
json转集合
  1. [Test]
  2. public void JsonToList()
  3. {
  4.     string json = "[{"Id": 1,"Name": "任我行网络教育有限公司","Url": "www.renwoxing.com"}, <br>            {"Id": 2,"Name": "百度","Url": "www.baidu.com"}]";
  5.     List<Site> sites = JsonConvert.DeserializeObject<List<Site>>(json);
  6.     Console.WriteLine(sites.Count);
  7. }
复制代码
 
4. 综合训练

结合反射,枚举,特性,扩展方法,完成综合练习。

  • 声明枚举如下:
    1. using System.ComponentModel;
    2. /**
    3. * 订单状态
    4. */
    5. public enum OrderStateEnum
    6. {
    7.     [Description("待支付")]
    8.     WaitPay,
    9.     [Description("待发货")]
    10.     WaitSend,
    11.     [Description("待收货")]
    12.     WaitReceive,
    13.     [Description("待评论")]
    14.     WaitComment,
    15.     [Description("已完成")]
    16.     Finish,
    17.     [Description("取消订单")]
    18.     Cancel
    19. }
    复制代码
     
  • 要求 封装OrderStateEnum的扩展 方法 GetDescription() ,效果如下
    1. string desc = OrderStateEnum.WaitPay.GetDescription();
    2. Console.WriteLine(desc); // 输出:待支付
    复制代码
     
 
   3. 具体实现
  1. /// <summary>
  2. /// 获取描述特性信息
  3. /// </summary>
  4. /// <param name="stateEnum"></param>
  5. /// <returns></returns>
  6. public static string GetDescription(this OrderStateEnum stateEnum)
  7. {
  8.     var type = stateEnum.GetType();
  9.     var fieldInfo = type.GetField(stateEnum.ToString());
  10.     var desc = fieldInfo.GetCustomAttribute<DescriptionAttribute>();
  11.     return desc.Description;
  12. }
复制代码
 
 
配套视频链接:

 
 
 

来源:https://www.cnblogs.com/xuyubing/archive/2023/06/02/17452369.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具