由C转向C需要注意的问题40
高平历史网 2020-06-20 08:10:07
映射
在许多情况下,我们需要一种方法,能够从元数据中访问属性,C#提供了对映射的支持以访问元数据。通过初始化MemberInfo类型对象,flection名字空间中的这个对象可以用来发现成员的属性,对元数据进行访问。
mberInfoinf=typeof(MyMath);
对MyMath类型调用typeof操作符,它返回一个由继承MemberInfo而生成的Type类型的变量。
下一步是对MemberInfo对象调用GetCustomAttributes,并将希望得到的属性的类型作为一个参数传递给GetCustomAttributes。我们将得到一个对象数组,数组的每个成员的类型都是BugFixAttribute。
object[]attributes;
attributes=tCustomAttributes(inf,typeof(BugFixAttribute));
我们就可以遍历这个数组了,打印BugFixAttribute对象的数组,代码下所示:
属性的打印
publicstaticvoidMain()
{
MyMathmm=newMyMath();
iteLine("CallingDoFunc(7).Result:{0}",
Func1(7));
//获取成员信息并使用它访问自定义的属性
mberInfoinf=typeof(MyMath);
object[]attributes;
attributes=
tCustomAttributes(inf,typeof(BugFixAttribute));
//遍历所有的属性
foreach(Objectattributeinattributes)
{
BugFixAttributebfa=(BugFixAttribute)attribute;
iteLine("\nBugID:{0}",gID);
iteLine("Programmer:{0}",ogrammer);
iteLine("Date:{0}",te);
iteLine("Comment:{0}",ment);
} }
类型发现
我们可以通过映象的方法来研究一个组合实体的内容,如果要建立需要显示组合体内部信息的工具或动态地调用组合体中的途径,这一方法是非常有用的。
通过映象的方法,我们可以知道一个模块、方法、域、属性的类型,以及该类型的每个方法的信号、该类支持的界面和该类的超级类。我们可以通过如下的形式,用ad静态方法动态地加载一个组合体:
ad(AssemblyName)
然后,可以将它传递到核心库中。
Assemblya=ad("l");
一旦加载了组合体,我们可以通过调用GetTypes返回一个Type对象数组。Type对象是映射的核心,它表示类、界面、数组、值和枚举等的类型定义。
Type[]types=tTypes();
组合休会返回一个类型的数组,我们可以使用foreach-loop结构显示该数组,其输出将有好几页文档之多,下面我们从中找一小段:
peCode
ringExpressionSet
F7Encoding$Encoder
gIterator
TLookupTable
1205typesfound
我们得到了一个内容为核心库中类型的数组,可以将它们都打印出来,该数组将有1205个项。
对一种类型映射我们也可以对组合体中一种类型进行映射。为此,我们可以使用GetType方法从组合体中解析出一个类型:
publicclassTester
{
publicstaticvoidMain()
{
//检查一个对象
TypetheType=tType("sembly");
iteLine("\nSingleTypeis{0}\n",theType);
}
}
输出如下所示:
sembly
发现成员
我们还可以得到所有成员的类型,显示所有的方法、属性、域,下面的代码演示了实现上述目标的代码。
Figure9GettingAllMembers
publicclassTester
{
publicstaticvoidMain()
{
//检查一个单一的对象
TypetheType=tType("sembly");
iteLine("\nSingleTypeis{0}\n",theType);
//获取所有的成员
MemberInfo[]mbrInfoArray=
tMembers(okupAll);
foreach(MemberInfombrInfoinmbrInfoArray)
{
iteLine("{0}isa{1}",
mbrInfo,rmat());
} }
}
尽管得到的输出还非常长,但在输出中我们可以得到如下面的不甘落后民示的域、方法、构造器和属性:
rings_localFilePrefixisaField
BooleanIsDefined(pe)isaMethod
or()isaConstructor
ringCodeBaseisaProperty
ringCopiedCodeBaseisaProperty
只发现方法
我们可能会只关心方法,而不关心域、属性等,为此,我们需要删除如下的对GetMembers的调用:
MemberInfo[]mbrInfoArray=
tMembers(okupAll);
然后添加调用GetMethods的语句:
mbrInfoArray=tMethods();
现在,输出中就只剩下方法了。
Output(excerpt)
BooleanEquals(ject)isaMethod
ringToString()isaMethod
ringCreateQualifiedName(ring,ring)
isaMethod
thodInfoget_EntryPoint()isaMethod
发现特定的成员
最后,为了进一步地缩小范围,我们可以使用FindMembers方法来发现某一类型的特定的方法。例如,在下面的代码中,我们可以只搜索以“Get”开头的方法。
publicclassTester
{
publicstaticvoidMain()
{
//检查一个单一的对象
TypetheType=tType("sembly");
//只获取以Get开头的成员
MemberInfo[]mbrInfoArray
ndMembers(thod,
fault,
lterName,"Get*");
foreach(MemberInfombrInfoinmbrInfoArray)
{
iteLine("{0}isa{1}",
mbrInfo,rmat());
} }
}
其输出的一部分如下所示:
pe[]GetTypes()isaMethod
pe[]GetExportedTypes()isaMethod
peGetType(ring,Boolean)isaMethod
peGetType(ring)isaMethod
semblyNameGetName(Boolean)isaMethod
semblyNameGetName()isaMethod
Int32GetHashCode()isaMethod
semblyGetAssembly(pe)isaMethod
peGetType(ring,Boolean,Boolean)isaMethod
动态调用
一旦发现一个方法,可以使用映射的方法调用它。例如,我们可能需要调用th中的Cos方法(返回一个角的余弦值)。为此,我们需要获得th类的类型信息,如下所示:
TypetheMathType=tType("th");
有了类型信息,我们就可以动态地加载一个类的实例:
ObjecttheObj=eateInstance(theMathType);
CreateInstance是Activator类的一个静态方法,可以用来对对象进行初始化。
有了th类的实例后,我们就可以调用Cos方法了。我们还需要准备好一个定义参数类型的数组,因为Cos只需要一个参数(需要求余弦值的角度),因此数组中只需要有一个成员。我们将在数组中赋予一个uble类型的Type对象,也就是Cos方法需要的参数的类型:
Type[]paramTypes=newType[1];
paramTypes[0]=tType("uble");
现在我们就可以传递方法的名字了,这个数组定义了Type对象中GetMethod方法的参数的类型:
MethodInfoCosineInfo=
tMethod("Cos",paramTypes);
我们现在得到了MethodInfo类型的对象,我们可以在其上调用相应的方法。为此,我们需要再次在数组中传入参数的实际值:
Object[]parameters=newObject[1];
parameters[0]=45;
ObjectreturnVal=voke(theObj,parameters);
需要注意的是,我创建了二个数组,第一个名字为paramTypes的数组存储着参数的类型,第二个名字为parameters的数组保存实际的参数值我们必须要非常强才能过关。如果方法需要二个参数,我们就需要使这二个数组每个保持二个参数。如果方法不需要参数,我们仍然需要创建这二个数组,只是无需在里面存储数据即可。
Type[]paramTypes=newType[0];
尽管看起来有点奇怪,但它是正确的。下面是完整的代码:
映射方法的使用
usingSystem;
flection;publicclassTester
{
publicstaticvoidMain()
{
TypetheMathType=tType("th");
ObjecttheObj=eateInstance(theMathType);
//只有一个成员的数组
Type[]paramTypes=newType[1];
paramTypes[0]=tType("uble");
//获得Cos()方法的信息
MethodInfoCosineInfo=
tMethod("Cos",paramTypes);
//将实际的参数填写在一个数组中
Object[]parameters=newObject[1];
parameters[0]=45;
ObjectreturnVal=voke(theObj,parameters);
iteLine(
"Thecosineofa45degreeangle{0}",returnVal);
} }
结论
尽管有许多小错误等着C++编程人员去犯,但C#的语法与C++并没有太大的不同,向新语言的转换是相当容易的。使用C#的有趣的部分是使用通用语言运行库越来越多的人开始抵制水电,这篇文章只能涉及几个重点问题。CLR和.NETFramework提供了对线程、集合、互联应用开发、基于Windows的应用开发等方面提供了更多的支持。语言功能和CLR功能之间的区分是非常模糊的,但组合在一起就是一种功能非常强大的开发工具了。
宝宝拉肚子能吃橙子吗动脉血管硬化是怎么回事衡阳白斑疯医院- 会站限制莺歌,会站砍31分4帽,太阳赢球,他抢了保罗的MVP
- 《雪中悍刀行2》宣发,5大主演披露,姜泥、青鸟新人选意外
- 2022宁夏公务员考试笔试时间确认7月9日至10日
- 自觉是喜欢一个人的时候一心一意
- 懂得念人之好,是职边锋更高级别的情商
- 宁夏艺术职业学院一行来丝路风味公司
- 像冰箱 微波炉等电器的污渍,不能用碱性太大的清洁剂,这种专用的多功能清洁剂,它是植物萃取精华,气味很
- 通威股份(600438.SH)2022-2024年员工持股计划已完成投资者购买 斥资约54.88
- 难怪鹿鼎记不敢续写天龙八部,你看扫地僧圆寂之后,谁是天下第一?
- 天下太平人寿董事长杨铮任职资格获批
- 关乎大资金动向!科创板“芯片”指数来了,42只样本股名单公布;上交所几大指数也调整,腾讯、美团等权重
- 张丰毅还给继女保时捷,亲儿子婚礼拒绝参加,只因亲儿子做了错事?