反射-优化及程序集等(用委托的方式调用需要反射调用的方法(或者属性、字段),而不去使用Invoke方法)
创建Delegate
(1).Delegate.CreateDelegate(Type, MethodInfo) : 创建指定类型的静态方法,
1.Type(委托类型)
2.MethodInfo(要创建的静态方法的信息,通过类的type.GetMethod( funcName , BindingFlags.IgnoreCase | BindingFlags.Static | BindingFlags.Public )获取)
3.例:typeof(string).GetMethod(“Equals", System.Reflection.BindingFlags.Public);
(2).Delegate.CreateDelegate(Type,Type,String):创建指定类型的的委托,该委托表示指定类的指定静态方法
1.Type(委托类型)
2.Type(类的类型)
3.String(方法名称)
(3).Delegate.CreateDelegate(Type,Object,String):创建指定类型的委托,该委托表示要对指定的类实例调用的指定实例方法
1.Type(委托类型)
2.Object(类的实例)
3.String(方法名称)
(4).Delegate.CreateDelegate(Type,Object,String,bool):创建指定类型的委托,该委托表示要对指定的类实例调用的指定实例方法,大小写敏感
1.Type(委托类型)
2.Object(类的实例)
3.String(方法名称)
4.bool(igonore case指示是否大小写敏感)
程序集、反射等相关
(1).C#编译原理
1.C#生成exe文件后,放在bin目录中。bin是binary(二进制)的缩写,但在bin目录中实际放的是IL文件,而不是二进制文件。
2.JIT将IL中间语言编译为二进制机械语言,但不是一次性全部编译完,而是用什么就编译什么,未编译前就是一堆字符串。
3.注册表记录哪种后缀名要用哪种程序打开。程序安装时会在注册表登记这些信息。exe默认用操作系统运行,但是因为操作系统不懂IL,于是交给FW运行。FW运行时会先找Main函数。默认配置文件(App.config)不会编译到exe里去,改动后不用重新生成,但要重启程序,因为只在打开时读一次。
4.exe下载到内存后叫assembly。class对应内存中type的对象
(2).程序集(Assembly) .exe .dll
1.所有.Net类都是定义在某个Assembly(程序集)中的,.Net基本类是定义在mscorlib.dll中。exe也可以看做是类库,也可以引用。.Net的exe也是Assembly,.Net中的exe和dll的区别就是exe中包含入口函数,其他没有区别,exe也可以当成dll那样引用、也可以反编译。
2.AppDomain.CurrentDomain.GetAssemblies();//获得程序所有的Assembly。应用程序域(AppDomain):一种边界,它由公共语言运行库(CLR - common language runtime)围绕同一应用程序范围内创建的对象建立(即,从应用程序入口点开始,沿着对象激活的序列的任何位置)。应用程序域有助于将在一个应用程序中创建的对象与在其他应用程序中创建的对象隔离,以使运行时行为可以预知。在一个单独的进程中可以存在多个应用程序域。应用程序域可以理解为一种轻量级进程。起到安全的作用。占用资源小。
3.System.Reflection.Assembly.GetExecutingAssembly();//获取正在执行的 程序集对象
4.Assembly.Load(“程序集名称,即dll的名字,不要带.dll后缀”)
5.Assembly.LoadFrom(“程序集实际路径”)
6.Assembly.Load(“”).CreateInstance(“命名空间.类”)
eg: var fullname = assembly.FullName
if (fullname.StartsWith(“Assembly-Sharp-Editor"))
(3).Type类
1.Type类可以叫做“类的类”,一个类型对应一个Type类的对象,通过Type对象可以获得类的所有的定义信息,比如类有哪些属性、哪些方法等。Type就是对类的描述。
2.JIT生成Type类的对象:只有在程序中第一次遇到某个类的时候,才会去加载这个类,并解析类的内容,然后生成对应的Type对象,并将类解析出来的信息装入Type对象中存入内存,方便以后复用。
(4).Type的一些方法
1.bool IsAssignableFrom(Type c)[is assignable from 可以被…赋值]:判断当前的类型的变量是不是可以接受c类型变量的赋值。(c类型变量是否实现当前类型,判断c类型变量是否实现接口)
2.bool IsInstanceOfType(object o):判断对象o是否是当前类的实例(当前类可以是o的类、父类、接口)
3.bool IsSubclassOf(Type c):判断当前类是否是类c的子类
4.bool IsInterface 判断当前类是否为接口
5.typeof(A).BaseType 为一个类的直接基类类型,不是基类的基类 例 B 继承自A, C继承自 B, 则typeof(C).BaseType.FullName = B
(5).获取Type的方法
1.Type t = typeof(Person)
2.Type t = p.GetType()
3.通过Assembly的GetType()方法( Type t = assembly.GetType(“命名空间.类名”))( 如果是通过程序集来取,里面的参数必须要是命名空间.类名)
assembly.CreateInstance是经过封装的Activator.CreateInstance方法.前者在安全上更有保证一些,其实就是判空了(判断type是否为空)一下.
如,assembly.CreateInstance(“命名空间.类名”) 等于 Type t = assembly.GetType("命名空间.类名”) if (null != t) { temp = Activator.CreateInstance(t); }
4. *类放在内存中就是type对象 Name:类名 FullName:命名空间.类名
5.type.GetCustomAttributes(typeof(ExportAttribute), false) 得到
(6).动态调用成员
1.调用Type的GetProperty方法可以根据属性名获得属性对象PropertyInfo, 主要成员:CanRead、CanWrite、PropertyType, 属性类型:SetValue、GetValue:读取值,设置值,第一个参数是实例对象,因为set、get要针对具体实例,最后一个参数null。type.GetProperty(“Age”).SetValue(p1, 30, null)
2.调用Type的GetMethod方法可以根据方法名获得方法对象MethodInfo,调用MethodBase 的Invoke方法就可以调用方法,第一个参数是实例对象,第二个参数是参数数组,如果没有参数设置为null。
(7).创建对象
1.Activator.CreateInstance(Type t)会动态调用类的无参构造函数创建一个对象,返回值就是创建的对象,如果类没有无参构造函数就会报错。(应用:通过配置文件动态创建对象。)
2.调用有参构造函数,有几个参数就传几个 Dog d=Activator.CreateInstance(t,"Japan") as Dog;
2.调用有参构造函数,有几个参数就传几个 Dog d=Activator.CreateInstance(t,"Japan") as Dog;
Attribute
1.Attribute的目的是为元素提供关联附加信息。其中,“[AttributeUsage(AttributeTargets.Class)] ”说明了Attribute提供附加信息的元素是Class,还可以是Method, Struct等
2.定义一个Attribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] //这里也声明此Attribute作用的类型
public class VersionAttribute : Attribute
{
public string Name { get; set; }
public string Date { get; set; }
public string Describtion { get; set; }
}
3.使用自定义的Attribute
[Version(Name = "hyddd", Date = "2009-07-20", Describtion = "hyddd's class”)]
public class MyCode
{
}
4.取得类的关联信息
public void xxx ()
{
var add = (VersionAttribute)Attribute.GetCustomAttribute (typeof(MyCode), typeof(VersionAttribute), false); // false处为Inherited, 该命名参数指定所指示的属性能否由派生类和重写成员继承
var axx = (typeof(MyCode)).GetCustomAttributes (typeof(VersionAttribute), false); //
add.Name //取得Name属性, 方案1
foreach(VersionAttribute em in axx)
foreach(VersionAttribute em in axx)
{
return em.Name //取得Name属性, 方案2
}
}
return em.Name //取得Name属性, 方案2
}
}