反射
- 通过Type类型的实例来访问类型的元数据
- 通过
obj.GetType()
或typeof()
获取一个Type类型的实例 - 在Type类型的实例上通过
GetProperties()
,GetMethods()
,GetCustomAttributes()
访问类型的各种东西 GetType()
只能在实例上调用,typeof()
给一个类型名就行,它是在编译时求值的- 验证一个对象的类型是否是某个类型:
bool CompareTo(object obj)
{
//反射写法
if (obj.GetType() != typeof(DateTime))
{
//
}
//is
if (obj is DateTime)
{
//
}
//我觉得这俩是一个意思
}
- 我记得以前看CLR via C#的时候说过,运行时会为每一个类型创建一个唯一的Type对象,然后每一个该类型的实例都会有一个指针,指向这个Type对象,所以判断一个实例是否是某个类型的这个功能,底层应该就是判断这个实例里存储的指针是否等于给定的类型的类型对象的指针
- 获取到一个
PropertyInfo
之后可以直接SetValue
,传值和要设置的对象的引用就行 - 获取到一个
MethodInfo
之后可以直接Invoke IsGenericType
判断是否是泛型类型,GetGenericArguments()
获取泛型参数的Type
nameof
- 编译时获取一个程序元素的名字,如果是完全限定名也只获取最后一个标识符
特性
- 可以利用特性指定与被修饰的构造有关的额外元数据,特性的作用是将额外的数据关联到某个程序元素上
- 返回值的特性需要加一个
return:
- .csproj文件中的
<PropertyGroup>
里的元素,都会注入为[assembly:]
特性 - 自定义特性继承
Attribute
,结尾加个Attribute
- 给特性加构造函数,在特性对象里存数据
- 只有常量值和typeof表达式才允许作为实参传到构造函数
- 如果特性有必须的属性值,要提供只读属性
- 提供相应的构造函数来初始化属性
AttributeUsageAttribute
特性用于自定义特性的时候添加一些限制- 第一个参数指定该特性可以修饰什么类型的元素,使用不恰当时会编译错误
AllowMultiple
限制是否可以在一个构造上添加多次
FlagAttribute
需要指定每个枚举项的值,1<<0
,1<<1
AttributeUsage
是编译器内建支持的Conditional
可以条件执行某些方法,用define定义宏,是否调用取决于调用者所在程序集中的预处理器标识符,因为他是靠编译器删掉调用代码来实现的Obsolete
用于将一个东西标记为作废的,可以添加额外的message和bool error来指定是否强制编译器报错