LINQ、反射和特性

来源:互联网 发布:血液问题人数调查数据 编辑:程序博客网 时间:2024/06/05 20:41

一、LINQ

1、使用LINQ做查询
 var masterList = new List<MartialArtsMaster>()
            {
初始化的对象及它的信息,
初始化的对象及它的信息,
...
};
(1)表达式写法
   var res = from m in masterList
             where m.Level > 8
select m;
    foreach(var temp in res)
{
Console.WriteLine(temp);
}
说明:初始化了一个叫masterList的集合
       from m in masterList         m表示在这个集合中每一个对象
   where m.Level > 8           表示一个判断,当这个对象的某个字段大于8时
   select m                    返回m
   
public override string ToString()
    {
    return string.Format("Id:{0},Name:{1},Age:{2},Mengpai:{3},
Kongfu:{4},Level:{5}",Id, Name, Age, Mengpai, Kongfu, Level);
    }
如果返回m要返回它的具体数据时,可以在MartialArtsMaster类中重写ToString方法
如果要返回m中特定的一个字段,可以使用 select m.字段的方式
                             例如:select m.Name; select m.Level;
 
(2)扩张方法的写法
    var res = masterList.Where(m => m.Level >8);
    使用集合masterList下的Where方法,(中一般写一个lambda表达式)
                                  参数 => 判断条件
 
2、多个判断语句
(1)、表达式写法
     from m in masterList        
   where m.Level > 8 && m.Mengpai == "丐帮"           
   select m;           


(2)、扩展方法的写法    
var res = masterList.Where(m => m.Level >8 && m.Mengpai == "丐帮");


3、联合查询
要查询多个集合 


    var res = from m in masterList
              from k in kongfuList
              where m.Kongfu == k.Name && k.Power > 90
              select new { master = m, kongfu = k };new 一个 m 和 k
当需要把m和k都显示的话,可以 select new { master = m, kongfu = k };
 
联合查询扩展方法:  
var res = masterList.SelectMany(m => kongfuList,
          (m, k) => new { master = m, kongfu = k }).Where
                (x => x.master.Kongfu == x.kongfu.Name && x.kongfu.Power > 90); 
扩展方法都是使用集合中的方法 
 
4、对查询结果做排序
表达式写法:
(1)、顺序
    var res = from m in masterList
              where m.Level > 8 && m.Mengpai == "丐帮"
              orderby m.Age
              select m;
使用 orderby 关键字,一般都放在 where 判断条件后面,默认是从小到大排序
(2)、倒序
var res = from m in masterList
              where m.Level > 8 && m.Mengpai == "丐帮"
              orderby m.Age descending
              select m;  
要使用倒序排序,可以在字段后面加 descending 关键字 
(3)、按照多个字段排序
     orderby m.Level,m.Age
    当Level一样时,再按照Age的大小排序  

扩展方法的写法:
(1)、顺序
    var res = masterList.Where
          (m => m.Level > 8 && m.Mengpai == "丐帮").OrderBy(m => m.Level);
使用集合masterList下的Where方法,在判断条件后使用OrderBy方法
(2)、倒序
    var res = masterList.Where
          (m => m.Level > 8 && m.Mengpai == "丐帮").OrderByDescending
  (m => m.Level);
使用OrderByDescending可以使字段倒序输出
(3)、a按照多个字段排序
    var res = masterList.Where
          (m => m.Level > 8 && m.Mengpai == "丐帮").OrderBy
  (m => m.Level).ThenBy(m => m.Age);
在第一个排序后面使用 TheBy 输入第二个要排序的字段 
 
5、使用 join on 集合联合  
var res = from m in masterList
              join k in kongfuList on m.Kongfu equals k.Name
              select new { master = m, kongfu = k };
    join 把两个集合联合, on 后面跟联合条件


当有需要对这个输出进行判断条件或排序时
    var res = from m in masterList
              join k in kongfuList on m.Kongfu equals k.Name
  where k.Power > 90
  orderby m.Age
              select new { master = m, kongfu = k };
在 join on 后面添加 where 或 orderby 

6、分组查询 into groups         使用与需要联合的两个集合上
    var res = from k in kongfuList
              join m in masterList on k.Name equals m.Kongfu
              into groups                                        
              orderby groups.Count()
              select new { Kongfu = k,count = groups.Count() }; 
说明:masterList中的对象要根据 kongfuList中的对象分组
      groups就相当于符合联合条件的对象的集合
      groups.Count()可以返回这个groups集合中的元素数,然后进行排序


7、按照自身字段分组 group by 使用与在一个集合中按照字段分组
ar res = from m in masterList
             group m by m.Mengpai into g
             select new {count = g.Count(),key = g.Key };       
说明:在m(对象)中按照m.Mengpai(字段)分组,这个组假设为g
      g.Count()获取g中的元素数,g.Key表示这个字段的属性分在的哪个组


8、量词操作符 any all 判断集合中是否满足某个条件   
    bool res = masterList.Any(m => m.Mengpai == "丐帮");
只要有一个满足条件就返回 true

bool res = masterList.All(m => m.Mengpai == "丐帮");
集合中的对象都满足条件时返回true
 
Any 任一个对象条件满足即为 true
    All 所有对象都满足即为 true


二、反射和特性

    元数据:程序是用来处理数据的,文本和特性都是数据,而程序本身(类的定义和BLC
            中的类)也是数据,有关程序及其类型的数据叫元数据,它们保存在程序
的程序集中
反射:程序在运行时,可以查看其它程序集或其本身的元数据。
      一个运行的程序在查看本身的元数据或者其它程序集的元数据的行为叫反射
  
1、Type类
说明:预定义类型(int,string,long)BCl中的类型(Console,IEnumerable)和程序员
    自定义的类型(MyClass,MyDel),每种类型都有自己的成员和特性
      BCL声明了一个Type的抽象类,用来包含类型的特性,使这个类的对象能获取程序
    使用的类型的信息

(1)、声明
注意:Type类是个抽象类,所以不能直接实例


每个类对应一个Type对象,这个Type对象存储了这个类中
    有哪些方法跟哪些数据哪些成员!
    MyClass my = new MyClass();
    Type type = my.GetType();  
通过类实例的对象中GetType()方法获取这个对象所属类的Type对象
一个类中的数据是存储在对象中的,但是Type对象只存储类的成员
    (反射回来的没有具体的数据)

    type.Name获取类的名字
    type.Namespace获取类所在的命名空间
    type.Assembly获取程序集


(2)、反射所有的字段名称
    FieliInfo[] 用于存储字段的信息
    FieldInfo[] array = type.GetFields();
    foreach (FieldInfo info in array)
        {
            Console.Write(info.Name+" ");
        }

(3)、反射所有的属性名称
    PropertyInfo[]用于存储属性的信息
    PropertyInfo[] array2 = type.GetProperties();
    foreach (PropertyInfo info in array2)
        {
            Console.Write(info.Name+" ");
        }

(4)、反射所有的方法名称
    MethodInfo[]用于存储方法的信息
    MethodInfo[] array3 = type.GetMethods();
    foreach (MethodInfo info in array3)
        {
            Console.Write(info.Name+" ");
        }
    通过Type对象可以获取它对应的类的所有public成员

2、Assembly程序集类
    Assembly assem = my.GetType().Assembly; 
    Console.WriteLine(assem.FullName);
通过类的Type对象获取它所在的程序集 Assembly
使用FullName方法获取程序集的完整名称

获取程序集类中Type类对象的信息并输出:
    Type[] types = assem.GetTypes();
    foreach (var type in types)
        {
            Console.WriteLine(type);
        }

3、特性
(1)、Obsolete特性:


例子:
    [Obsolete("这个方法过时了,使用NewMethod代替")]            
    static void OldMethod()
    {
        Console.WriteLine("OldMethod");
    }
    static void NewMethod()
    {


    }
    static void Main(string[] args)
    {
        OldMethod();
        Console.ReadKey();
    }

说明:在一个方法上加[Obsolete]表示下面这个方法被弃用了,但是还是能够被调用的
      在[Obsolete()] 括号中输入提示语句,当调用这个过时的方法时会显示提示语句

[Obsolete("这个方法过时了,使用NewMethod代替",true)]
后面的bool值代表是否应该标记为错误, true 即标记为错误,使用这个方法就会报错
                                     false 为不标记为错误,只会出现警告

(2)、Conditional特性:
    #define IsTest
[Conditional("IsTest")]
    static  void Test1()
    {
        Console.WriteLine("test1");
    }
    static void Test2()
    {
        Console.WriteLine("test2");
    }

说明:当一个方法被多次调用,需要取消该方法的所有调用时,
          可以在方法上加[Conditional(" ")] 括号里要输入有效标识符!
  在using引用上面定义 #define IsTest 与Conditional后输入的标识符匹配
         相同则方法被调用,把#define这句注释掉则所有方法都不调用

(3)、调用者信息特性
     static void PrintOut(string str,
                     [CallerFilePath] string fileName ="",
                         [CallerLineNumber]int lineNumber = 0,
[CallerMemberName]string methodName = "")
        {
            Console.WriteLine(str);
            Console.WriteLine(fileName);
            Console.WriteLine(lineNumber);
            Console.WriteLine(methodName);
        }
static void Main(string[] args)
    {
           
        PrintOut("123");
}
输出:123
      E:\vs\C#\WinForm\14\15\Program.cs
      50
      Main
说明:在字符前加[CallerFilePath]会返回代码所在文件的路径地址
  在字符前加[CallerLineNumber]会返回代码的总行数
  在字符前加[CallerMemberName]会返回这个方法在哪个函数中被调用
  
(4)、DebuggerStepThrough特性
    在方法前加[DebuggerStepThrough]可以跳过debugger的单步调试,不进入该方法
    在调试中,知道某些方法不可能出错,要跳过这些方法调试可以使用这个特性 
  
特性:是一种我们想程序集增加元数据的语言结构
      将应用了特性的程序结构叫目标
      设计用来获取和使用元数据的程序(对象浏览器)叫做特性的消费者
      .Net 预定了很多特性,可以声明自定义特性   
  
(5)、自定义特性
    [AttributeUsage(AttributeTargets.Class)] 
    sealed class MyTestAttribute :System.Attribute
    {
        public string Descriptioin { get; set; }
        public string VersionNumber { get; set; }
        public int ID { get; set; }
   public MyTestAttribute(string des)
        {
            this.Descriptioin = des;
        }
    }
1、自定义特性类的后缀以Attribute结尾
    2、需要继承System.Attribute
    3、一般情况下声明为sealed(声明后不可被继承)
    4、一般情况下特性类用来表示目标结构的一些状态(定义一些字段、属性、一般不定义方法)  
5、在自定义特性类前加[AttributeUsage(AttributeTargets.Class)] 
                     表示该特性可以运用到类上
6、[MyTest] 当我们使用特性的时候,后面的Attribute不用写
7、当我们使用一个特性类时,相当于调用了这个特性类的构造方法
   [MyTest("简单的特性类")]调用该特性时,就要给它一个参数
8、通过制定属性的名字,给属性赋值,叫命名参数
       [MyTest("简单的特性类",ID =100)] 


使用:
     Type type = typeof(Program);
     Object[] array = type.GetCustomAttributes(false);     
     MyTestAttribute mytest = array[0] as MyTestAttribute; 
     Console.WriteLine(mytest.Descriptioin);              
     Console.WriteLine(mytest.ID);
 
输出:简单的特性类
      100
  
说明:  
通过typeof(类名)也可以获取type对象
获取type中所有的特性信息,会返回一个Object类型的数组
把这个数组转换成特性类的类型,相当于会实例化一个特性类的对象
可以通过这个对象获取特性类中定义的字段
原创粉丝点击