二十二 反射
首先说明是反射,为什么要使用反射
反射提供的是一种封装程序集、模块和类型的对象。通过反射可以动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。
这是官方的定义,反射往往是针对未知的东西,扩展,兼容。
常说,反射性能差 为什么还要使用反射:
1. 机能 现在的机器 大都是双核了,机能已经不是 多少年前能比了。
2. 如果使用反射能简化程序代码,或者能有更好的可读性,扩展性. 那么确实可以不用去在意那么一点性能损失
3. 使用反射往往都是在 程序初始化,或者不常用的地方。
System.Type 类型。
使用反射 必不可少的玩意儿
Type 为 System.Reflection 功能的根,也是访问元数据的主要方式。使用 Type 的成员获取关于类型声明的信息,如构造函数、方法、字段、属性 (Property) 和类的事件,以及在其中部署该类的模块和程序集。
表示某个类型是唯一的 Type 对象;即,两个 Type 对象引用当且仅当它们表示相同的类型时,才引用相同的对象。这允许使用参考等式来比较 Type 对象。
如果没有 ReflectionPermission,代码只能访问已加载程序集的公共成员。这包括但不限于对 Object.GetType 的不受限制的访问、通过 Type.GetType 对公共导出类型的访问以及对 GetTypeFromHandle 的访问。Type 的某些属性 (Property)(例如 FullName 和 Attributes)可以在没有 ReflectionPermission 的情况下访问。
Type 为 System.Reflection 功能的根。 可以通过Type 获得 几乎类型的一切的信息
- Type.GetType(string)
- typeof(Object);
- (某个对象,列入string).GetType()
来个实例
Type e = typeof(aaaa);
这里是fields
- e.GetFields() {System.Reflection.FieldInfo[1]} System.Reflection.FieldInfo[]
- [0] {System.String Name} System.Reflection.FieldInfo {System.Reflection.RtFieldInfo}
+ [System.Reflection.RtFieldInfo] {System.String Name} System.Reflection.RtFieldInfo
+ base {System.String Name} System.Reflection.MemberInfo {System.Reflection.RtFieldInfo}
Attributes FamANDAssem | Family System.Reflection.FieldAttributes
+ FieldHandle {System.RuntimeFieldHandle} System.RuntimeFieldHandle
+ FieldType {Name = "String" FullName = "System.String"} System.Type {System.RuntimeType}
IsAssembly false bool
IsFamily false bool
IsFamilyAndAssembly false bool
IsFamilyOrAssembly false bool
IsInitOnly false bool
IsLiteral false bool
IsNotSerialized false bool
IsPinvokeImpl false bool
IsPrivate false bool
IsPublic true bool
IsSecurityCritical true bool
IsSecuritySafeCritical false bool
IsSecurityTransparent false bool
IsSpecialName false bool
- IsStatic false bool
MemberType Field System.Reflection.MemberTypes
这样得到fields 似乎没有私有字段。
这是 方法信息,同样 没有私有方法
- e.GetMethods() {System.Reflection.MethodInfo[6]} System.Reflection.MethodInfo[]
+ [0] {Void a1()} System.Reflection.MethodInfo {System.Reflection.RuntimeMethodInfo}
+ [1] {System.String a2()} System.Reflection.MethodInfo {System.Reflection.RuntimeMethodInfo}
+ [2] {System.String ToString()} System.Reflection.MethodInfo {System.Reflection.RuntimeMethodInfo}
+ [3] {Boolean Equals(System.Object)} System.Reflection.MethodInfo {System.Reflection.RuntimeMethodInfo}
+ [4] {Int32 GetHashCode()} System.Reflection.MethodInfo {System.Reflection.RuntimeMethodInfo}
+ [5] {System.Type GetType()} System.Reflection.MethodInfo {System.Reflection.RuntimeMethodInfo}
暂且放一放。
反射程序集
表示一个程序集,它是一个可重用、无版本冲突并且可自我描述的公共语言运行时应用程序构造块。
- Assembly.LoadFrom(".dll");
- Assembly.Load("");
- GetExecutingAssembly() 返回当前
如果不属于本项目的程序集 需要加上路径
来个列子
var o = Assembly.GetExecutingAssembly();
- o {StudyTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null} System.Reflection.Assembly {System.Reflection.RuntimeAssembly}
+ [System.Reflection.RuntimeAssembly] {StudyTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null} System.Reflection.RuntimeAssembly
CodeBase "file:///E:/SourceCode/Working/StudyTest/StudyTest/bin/Debug/StudyTest.EXE" string
+ EntryPoint {Void Main()} System.Reflection.MethodInfo {System.Reflection.RuntimeMethodInfo}
EscapedCodeBase "file:///E:/SourceCode/Working/StudyTest/StudyTest/bin/Debug/StudyTest.EXE" string
+ Evidence {System.Security.Policy.Evidence} System.Security.Policy.Evidence
FullName "StudyTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" string
GlobalAssemblyCache false bool
HostContext 0 long
ImageRuntimeVersion "v4.0.30319" string
IsDynamic false bool
IsFullyTrusted true bool
Location "E:\\StudyTest\\StudyTest\\bin\\Debug\\StudyTest.exe" string
+ ManifestModule {StudyTest.exe} System.Reflection.Module {System.Reflection.RuntimeModule}
+ PermissionSet {<PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true"/>} System.Security.PermissionSet
ReflectionOnly false bool
SecurityRuleSet Level2 System.Security.SecurityRuleSet
这样当前程序集就出来了,方法就不赘述了。 上msdn 慢慢看吧
总体来说 反射可以查看程序集,类,类型 的信息
关于特性:
这玩意儿也是可以大书特书的玩意儿
首先特性是一个类,运行时描述你的代码。
都是从Attribute 派生,如果要自定义也从那里面派生。
这是是一个关于 自定义属性的列子
我用了jimmy zhang的列子,因为他得就已经很好了,猛击这里
Type o = typeof(Demo);
var records = o.GetCustomAttributes(typeof(RecordAttribute), false); //这点我很疑惑
foreach (RecordAttribute record in records)
{
Console.WriteLine(" {0}", record);
Console.WriteLine(" 类型:{0}", record.RecordType);
Console.WriteLine(" 作者:{0}", record.Author);
Console.WriteLine(" 日期:{0}", record.Date.ToShortDateString());
if (!String.IsNullOrEmpty(record.Memo))
{
Console.WriteLine(" 备注:{0}", record.Memo);
}
}
[RecordAttribute("创建","测试","2012年1月2日22:10:52",Memo="演示")]
public class Demo {
}
public class RecordAttribute : Attribute
{
private string recordType; // 记录类型:更新/创建
private string author; // 作者
private DateTime date; // 更新/创建 日期
private string memo; // 备注
// 构造函数,构造函数的参数在特性中也称为“位置参数”。
public RecordAttribute(string recordType, string author, string date)
{
this.recordType = recordType;
this.author = author;
this.date = Convert.ToDateTime(date);
}
// 对于位置参数,通常只提供get访问器
public string RecordType { get { return recordType; } }
public string Author { get { return author; } }
public DateTime Date { get { return date; } }
// 构建一个属性,在特性中也叫“命名参数”
public string Memo
{
get { return memo; }
set { memo = value; }
}
}
然后 描述就得知了。
关于动态创建
Assembly asm = Assembly.GetExecutingAssembly();
Object obj = asm.CreateInstance("test", true);
public class test
{
}
也就意味着 可以不知道有test 这一个类, 然后动态调用。
或许是第三方 什么的 反正在不知道的情况下 调用
当然 如果有构造函数~
object[] p = { "aaaa" };
Assembly asm = Assembly.GetExecutingAssembly();
Object obj = asm.CreateInstance("test", true, BindingFlags.Default, null, p, null, null);
public class test
{
string a = null;
public test(string b) { a = b; }
}
这样就行了
然后就是调用 方法
其实这又是一个坑。。 发射我很少用到,这算是一个 底子吧,等需要了 再来详细的写