其实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