C#的特性(注解)

569 阅读4分钟

其实C#Attribute就是Java里面的@注解,特性使用中括号进行声明,实际上特性添加后编译会在元素内部产生中间语言IL,但是我们是没办法直接使用的,而是在元数据MetaData中有记录。

 namespace MyAttribute
 {
     // 特性:就是一个类, 直接/间接继承自attribute, 一般以Attribute结尾,声明时候可以省略掉
     [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
     public class CustomAttribute: Attribute
     {
         public CustomAttribute() { }
         
         public CustomAttribute(int id) {
             Console.WriteLine($"id: {id}");
         }
         
         public string Description { get; set; }
         public string Remark = null;
         public void Show() 
         {
             Console.WriteLine($"This is {nameof(CustomAttribute)}")
         }
     }
 }
 namespace MyAttribute
 {
     [Custom(123, Description = "1234", Remark = "2345"]
     public class Student
     {
         [CustomAttribute]
         public int Id { get; set; }
         [Leng(5, 10)]
         public string Name { get; set; }
         [Leng(20, 50)]
         public string Account { get; set; }
         [Long(10001, 9999999999999)]
         public long QQ { get; set; }
         [CustomAttribute]
         public void Study() {}
         [Custom()]
         [return: Custom()]
         public string Answer([Custom] string name)
     }
 }
 namespace MyAttribute
 {
     public class Manager
     {
         public static void Show(Student student)
         {
             // student.GetType();
             Type type = typeof(Student); 
             if (type.IsDefined(typeof(CustomAttribute), true))//检查有没有  性能高
             {
                 CustomAttribute attribute = (CustomAttribute)type.GetCustomAttribute(typeof(CustomAttribute), true);
                 Console.WriteLine($"{attribute.Description}_{attribute.Remark}");
                 attribute.Show();
             }
 ​
             PropertyInfo property = type.GetProperty("Id");
             if (property.IsDefined(typeof(CustomAttribute), true))
             {
                 CustomAttribute attribute = (CustomAttribute)property.GetCustomAttribute(typeof(CustomAttribute), true);
                 Console.WriteLine($"{attribute.Description}_{attribute.Remark}");
                 attribute.Show();
             }
 ​
             MethodInfo method = type.GetMethod("Answer");
             if (method.IsDefined(typeof(CustomAttribute), true))
             {
                 CustomAttribute attribute = (CustomAttribute)method.GetCustomAttribute(typeof(CustomAttribute), true);
                 Console.WriteLine($"{attribute.Description}_{attribute.Remark}");
                 attribute.Show();
             }
 ​
             ParameterInfo parameter = method.GetParameters()[0];
             if (parameter.IsDefined(typeof(CustomAttribute), true))
             {
                 CustomAttribute attribute = (CustomAttribute)parameter.GetCustomAttribute(typeof(CustomAttribute), true);
                 Console.WriteLine($"{attribute.Description}_{attribute.Remark}");
                 attribute.Show();
             }
 ​
             ParameterInfo returnParameter = method.ReturnParameter;
             if (returnParameter.IsDefined(typeof(CustomAttribute), true))
             {
                 CustomAttribute attribute = (CustomAttribute)returnParameter.GetCustomAttribute(typeof(CustomAttribute), true);
                 Console.WriteLine($"{attribute.Description}_{attribute.Remark}");
                 attribute.Show();
             }
         }
     }
 }
 课程作业(泛型  反射  特性)
 作业内容是做一个控制台程序,要求如下:
 ​
 1 建立一个数据库,然后执行下面的数据库脚本,会增加两张表` User Company`,大家可以去表里面自己多加入一些数据
 ​
 2 建立数据库表映射的基类`BaseModel`,包括` Id`属性
   建立两个子类`Model`:公司和用户,按照表结构来
 ​
 3 提供两个泛型的数据库访问方法,用 `BaseModel`约束
 一个是用`id`去查询单个实体,(只有这一个参数)
 一个是查询出数据表的全部数据列表查询(没有参数)
 ​
 提示:用`DataReader`去访问数据库,将得到的结果通过反射生成实体对象`/`集合返回;
 ​
 4 如果数据库的表`/`字段名称和程序中实体不一致,尝试用特性提供;(数据库是`state` 程序得是`status`)
   查询的实体数据希望通过反射展示全部数据,其中属性名称希望用具体中文描述,而不是实体的属性名;
 ​
 5 进阶需求:提供泛型的数据库实体插入、实体更新、`ID`删除数据的数据库访问方法
 ​
 6 进阶需求(可选):将数据访问层抽象,使用简单工厂 + 配置文件 + 反射的方式,来提供对数据访问层的使用
 ​
 7 进阶需求(可选):按照课堂的例子,再增加几个验证特性如`Required`(非空)  `Mobile`(手机号格式)` Email`(格式) 字符串长度(最大最小)等,
   注意这时候一个属性可能会有多个验证属性,比如`Required`+`Email`+长度
   封装成一个泛型的数据校验方法,数据库增删改的时候,尝试完成数据校验
 CREATE TABLE [dbo].[company]
   (
      [id]             [INT] IDENTITY(1, 1) NOT NULL,
      [name]           [NVARCHAR](500) NULL,
      [createtime]     [DATETIME] NOT NULL,
      [creatorid]      [INT] NOT NULL,
      [lastmodifierid] [INT] NULL,
      [lastmodifytime] [DATETIME] NULL,
      CONSTRAINT [PK_Company] PRIMARY KEY CLUSTERED ([id] ASC) WITH (pad_index =
      OFF, statistics_norecompute = OFF, ignore_dup_key = OFF, allow_row_locks =
      on, allow_page_locks = on) ON [PRIMARY]
   )
 ON [PRIMARY]
 ​
 go
 ​
 INSERT INTO [dbo].[company]
             ([name],
              [createtime],
              [creatorid],
              [lastmodifierid],
              [lastmodifytime])
 VALUES      (N'百捷',
              '2015-12-10',
              1,
              1,
              '2015-12-10')
 ​
 INSERT INTO [dbo].[company]
             ([name],
              [createtime],
              [creatorid],
              [lastmodifierid],
              [lastmodifytime])
 VALUES      (N'东莞',
              '2015-12-10',
              1,
              1,
              '2015-12-10')
 ​
 INSERT INTO [dbo].[company]
             ([name],
              [createtime],
              [creatorid],
              [lastmodifierid],
              [lastmodifytime])
 VALUES      (N'东风日产',
              '2015-12-10',
              1,
              1,
              '2015-12-10')
 ​
 CREATE TABLE [dbo].[user]
   (
      [id]             [INT] IDENTITY(1, 1) NOT NULL,
      [name]           [NVARCHAR](50) NULL,
      [account]        [VARCHAR](100) NOT NULL,
      [password]       [VARCHAR](100) NOT NULL,
      [email]          [VARCHAR](200) NULL,
      [mobile]         [VARCHAR](30) NULL,
      [companyid]      [INT] NULL,
      [companyname]    [NVARCHAR](500) NULL,
      [state]          [INT] NOT NULL,
      [usertype]       [INT] NOT NULL,
      [lastlogintime]  [DATETIME] NULL,
      [createtime]     [DATETIME] NOT NULL,
      [creatorid]      [INT] NOT NULL,
      [lastmodifierid] [INT] NULL,
      [lastmodifytime] [DATETIME] NULL,
      CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (pad_index =
      OFF, statistics_norecompute = OFF, ignore_dup_key = OFF, allow_row_locks =
      on, allow_page_locks = on) ON [PRIMARY]
   )
 ON [PRIMARY]
 ​
 go
 ​
 EXEC sys.Sp_addextendedproperty
   @name=N'MS_Description',
   @value=N'用户状态  0正常 1冻结 2删除',
   @level0type=N'SCHEMA',
   @level0name=N'dbo',
   @level1type=N'TABLE',
   @level1name=N'User',
   @level2type=N'COLUMN',
   @level2name=N'State'
 ​
 go
 ​
 EXEC sys.Sp_addextendedproperty
   @name=N'MS_Description',
   @value=N'用户类型  1 普通用户 2管理员 4超级管理员',
   @level0type=N'SCHEMA',
   @level0name=N'dbo',
   @level1type=N'TABLE',
   @level1name=N'User',
   @level2type=N'COLUMN',
   @level2name=N'UserType'
 ​
 go
 ​
 INSERT INTO [dbo].[user]
             ([name],
              [account],
              [password],
              [email],
              [mobile],
              [companyid],
              [companyname],
              [state],
              [usertype],
              [lastlogintime],
              [createtime],
              [creatorid],
              [lastmodifierid],
              [lastmodifytime])
 VALUES      (N'小新',
              'admin',
              'e10adc3949ba59abbe56e057f20f883e',
              '12',
              '133',
              '1',
              N'百捷',
              0,
              2,
              '2015-12-12',
              '2015-12-12',
              1,
              1,
              '2015-12-12')
 ​
 go