c#

位置:IT落伍者 >> c# >> 浏览文章

C#反射浅析


发布日期:2023年09月16日
 
C#反射浅析
首先了解C#反射的概念反射是一个运行库类型发现的过程通过反射可以得到一个给定程序集所包含的所有类型的列表

这个列表包括给定类型中定义的方法字段属性和事件也可以动态的发现一组给定类支持的借口方法的参数和其他

相关信息如基类命名空间数据清单等

C#反射命名空间详细介绍

SystemReflection命名空间内的各类型

) Assembly通过它可以加载了解和操纵一个程序集

) AssemblyName 通过它可以找到大量隐藏在程序集的身份中的信息如版本信息区域信息等

) EventInfo 事件的信息

) FieldInfo 字段的信息

) MethodInfo 方法的信息

) ParameterInfo 参数的信息

) PropertyInfo 属性的信息

) MemberInfo 是抽象基类为 EventInfoFieldInfo MethodInfoPropertyInfo等类型定义了公共的行为

) Module 用来访问带有多文件程序集的给定模块

SystemType类

SystemType支持的成员可以分为这样几类

) Is*** 用来检查一个类型的元数据如IsAbstractIsClassIsValueType等等

) Get*** 用来从类型得到指定项目如GetEvent()得到类型的一个指定的事件(EventInfo)

另外这些方法都有一个单数版本和一个复数版本如GetEvent()对应有一个复数版本GetEvents()

该方法返回一个相关的EventInfo数组

) FindMembers() 根据查询条件返回一个MemberInfo类型的数组

)GetType() 该静态方法根据一个字符串名称返回一个Type实例

)InvokeMember() 对给定项目进行晚期绑定

得到一个Type类型实例的三种方法

因为Type是一个抽象类所以不能直接使用new关键字创建一个Type对象

)使用SystemObjectGetType()

Person pe=new Person() //定义pe为person类的一个对象

Type t=peGetType()

)使用SystemTypeGetType()静态方法参数为类型的完全限定名

Type t=TypeGetType(EntityPerson 该方法被重载允许指定两个布尔类型的参数一个用来控制当前类型不能找到时是否抛出异常

另一个用来指示是否区分字符串大小写

Type t=TypeGetType(EntityPersonfalsetrue) 注意到传入的字符串并没有包含类型所在的程序集信息此时该类型便被认为是定义在当前执行的程序集中的

要得到一个外部私有程序集的类型元数据时字符串参数必须使用类型完全限定名加上类型所在程序集的友好名字

Type t=TypeGetType(EntityPersonEntity //Entity即为类型所在程序集的友好名字 嵌套类型传入的字符串可以指定一个+标记来表示一个嵌套类型

如希望得到一个嵌套在person类中的枚举类型City的类型信息则可以这样

Type t=TypeGetType(Entityperson+City

)使用typeof运算符

Type t=typeof(person) 三种方法的比较

使用第一种方法必须先建立一个实例而后两种方法不必先建立实例但使用typeof运算符仍然需要知道类型的编译时信息

而使用SystemTypeGetType()静态方法不需要知道类型的编译时信息所以是首选方法

一个最简单的C#反射实例首先编写类库如下

namespace ReflectionTest

{

public class WriteTest

{

//带参数的公共方法

public void WriteString(string s int i)

{

ConsoleWriteLine(WriteString: + s + iToString())

}

//带一个参数的静态方法

public static void StaticWriteString(string s)

{

ConsoleWriteLine(StaticWriteString: + s)

}

//不带参数的静态方法

public static void NoneParaWriteString()

{

ConsoleWriteLine(NoParaWriteString

}

}

}

class TestApp

{

public static void Main()

{

Assembly ass;

Type type;

Object obj;

//用来测试静态方法

Object any = new Object()

//指定类库文件必须使用绝对路径不能使用相对路径

ass = AssemblyLoadFile(@D:\Source Code\C#Sudy\Reflection\\ReflectTestdll

//命名空间和类的名字必须一起指定

type = assGetType(ReflectionTestWriteTest

/**//*example*/

MethodInfo method = typeGetMethod(WriteString

string test = test;

int i = ;

Object[] parametors = new Object[]{testi};

//在例子种必须实例化反射要反射的类因为要使用的方法并不是静态方法

//创建对象实例

obj = assCreateInstance(ReflectionTestWriteTest

//执行带参数的公共方法

methodInvoke(obj parametors)

//methodInvoke(any parametors)//异常必须实例化反射要反射的类因为要使用的方法并不是静态方法

/**//*example*/

method = typeGetMethod(StaticWriteString

methodInvoke(null new string[] { test}) //第一个参数忽略

//对于第一个参数是无视的也就是我们写什么都不会被调用

//即使我们随便new了一个any这样的Object当然这种写法是不推荐的

//但是对应在例子种我们如果Invoke的时候用了类型不一致的实例来做为参数的话将会导致一个运行时的错误

methodInvoke(obj new string[] { test})

methodInvoke(any new string[] { test})

/**//*example*/

method = typeGetMethod(NoneParaWriteString //调用无参数静态方法的例子这时候两个参数我们都不需要指定用null就可以了s

methodInvoke(null null)

}

}

从上面的总结中可以看出对于外部调用的动态库应用反射时要用到AssemblyLoadFile()然后才是获取类型执行方法等

当用反射创建当前程序集中对象实例或执行某个类下静态方法时只需通过TypeGetType(类的完整名

               

上一篇:C#操控条形码扫描枪

下一篇:c#实现文字由左向右滚动