学习LabVIEW(二)——操作.NET泛型类

2015-08-20 09:24:09   来源:eefocus   

关键字: LabVIEW  NET  泛型类

    误入歧途的一天。昨天晚上我看见http://digital.ni.com/public.nsf/allkb/DC41DCDA972642CF8625787E00732DDD说LabVIEW不支持.NET的泛型,如果要用,可以用C#写一个包装类。我就不信邪了,即使LabVIEW的语言层面不支持,我们也可以用.NET框架提供的Reflection的能力来实现任何我们想要实现的目标吧,用不着大动干戈写C#代码。于是我今天就试了试,最后发现,还是写C#代码来得比较方便,尽管我们用纯LabVIEW实现了泛型类的操作。
    用Reflection这样的机制操作泛型类,首先需要对.NET框架的基本对象模型有些了解。.NET的对象模型和CPython的对象模型有许多共通之处,比如,对象实例会包含一个执行类型对象的指针,这就是可以在运行时获取对象类型信息的基石。这里有一个非常重要的概念,就是类型对象,所谓类型对象就是代表类型的对象,这一点和CPython的对象模型简直不能更像,类型也是对象。知道了这一点,问题就好解决了。首先构造泛型类填充类型之后的类的对象,再由类对象来生成类实例。
    我们挑选System.Collections.Generic.Dictionary作为实验对象。这个泛型类我们需要填充两个类型参数,一个是Key的类型,一个是Value的类型。
    首先,获取没有填充类型参数的Dictionary类对象。类对象可以使用
System.Type.GetType("类名")
这种方式获取。然而,没有填充类型的Dictionary的名字是什么呢?在页面https://msdn.microsoft.com/zh-cn/library/system.type.makegenerictype(v=vs.100).aspx?cs-save-lang=1&cs-lang=cpp#code-snippet-3中C++的例子我们就能发现它的名字是System.Collections.Generic.Dictionary`2。
学习LabVIEW(二)——操作.NET泛型类

上图有一点需要注意。“调用节点”不仅可以调用普通的方法,也可以调用类的静态方法。具体做法就是类实例的输入端口什么也不接,然后在节点的右键菜单中选择相应的类名。类型选择的时候要注意,如果要用System.String, System.Int32, 以及System.Type这些类型时,要去mscorlib中找,选择器列出来的项目中没有这些,如下图所示:
学习LabVIEW(二)——操作.NET泛型类

    现在我们得到了没有填充类型参数的Dictionary,如何在没有语言支持的情况下填充参数呢(C#等.NET语言提供了语言支持可以用诸如Dictionary这样的语法)?答案就是MakeGenericType。类型对象的MakeGenericType方法的参数为Type[],数组中的类型对象将用来填充泛型类的类型参数,返回填充之后的具体类型。
    为了构造一个Type[],我一开始用的方法是System.Array的CreateInstance,但是发现它在LabVIEW中不能转换成Type[],因此也无法传递给MakeGenericType。最后找到的解决办法是使用LabVIEW自带的数组类型,往里面添加.NET的类型对象即可,LabVIEW会自动把它转化成Type[],如下图所示:
学习LabVIEW(二)——操作.NET泛型类

上面的程序最终生成了一个
System.Collections.Generic.Dictionary
的实例。
    有了一个类型对象,如何生成类的实例?答案是System.Activator。把生成的类型对象作为参数传递给Activator的静态方法CreateInstance,我们即可得到类的实例,如下图所示:
学习LabVIEW(二)——操作.NET泛型类
    上面的实验就像一场诗情画意的旅行,然而别高兴得太早,真正的噩梦从现在才开始。通过CreateInstance生成的
System.Collections.Generic.Dictionary
的实例会被当成System.Object,这是由CreateInstance返回值类型决定的。在C#中,我们可以用一个强制类型转换,把它转换成Dictionary,可是LabVIEW中似乎做不到这一点,即使提供了“类型转换”节点,然而并不能作我们需要的转换。
    LabVIEW把我们的Dictionary当做Object,我们无法使用“调用”节点来调用Dictionary的方法了。这个问题怎么解决?答案就是Reflection,利用类型对象的GetMethod方法获取MethodInfo,再通过MethodInfo的Invoke方法实现方法的调用。真正麻烦之处在于,Invoke需要传入一个System.Object[],作为调用方法的参数。因此,为了调用方法,我们还需要首先构造这个参数列表。
[1] [2]
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

推荐阅读

编辑:什么鱼
本文引用地址: http://www.eeworld.com.cn/Test_and_measurement/2015/0820/article_12845.html
[发表评论]
[加入收藏]
[打印本页]
[关闭窗口]
[返回顶部]
[RSS订阅]
小广播
每日新闻
最热点击
本周热门资源推荐
EEWORLD独家
论坛精华
精选博文