• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > 在C++中反射调用.NET的方法(三)

在C++中反射调用.NET的方法(三)

作者:深蓝医生 字体:[增加 减小] 来源:互联网 时间:2017-05-28

深蓝医生 通过本文主要向大家介绍了c++ 反射,c++子类调用父类方法,c++闰年的计算方法,c++排序方法,c++使用方法等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

在.NET与C++之间传输集合数据

上一篇《在C++中反射调用.NET(二)》中,我们尝试了反射调用一个返回DTO对象的.NET方法,今天来看看如何在.NET与C++之间传输集合数据。

使用非泛型集合的委托方法

先看看.NET类中的一个返回列表数据的方法:

//返回List或者数组,不影响 C++调用
 public List<IUserInfo> GetUsers(string likeName)
 {
 List<IUserInfo> users = new List<NetLib.IUserInfo>();
 for (int i = 0; i < 10; i++)
 {
 IUserInfo userinfo = GetUserByID(i);
 userinfo.Name += likeName;
 users.Add(userinfo);
 }
 //return users.ToArray();
 return users;
 }
 public IUserInfo GetUserByID(int userId)
 {
 IUserInfo userinfo= EntityBuilder.CreateEntity<IUserInfo>();
 userinfo.ID = userId;
 userinfo.Name = "姓名_" + userId;
 userinfo.Birthday = new DateTime(1980, 1, 1);
 return userinfo;
 }
</div>

该方法没有什么复杂业务逻辑,就是将传递进来的参数给DTO对象,创建包含10个这样的对象的列表并返回而已。

对于 GetUsers方法,我们可以创建下面的委托方法来绑定:

Func<String, IEnumerable> fun;
</div>

注意这里使用的是非泛型的 IEnumerable接口,在C++需要使用下面这个命名空间:

using namespace System::Collections;
</div>

那么为何不能使用泛型集合呢?

using namespace System::Collections::Generic;
</div>

因为在C++端,没有直接引用用户项目的.NET程序集,并不知道泛型集合类型的具体类型,IUserInfo这个接口无法直接访问,好在IEnumerable<T>也是继承 IEnumerable 的,所以可以当做非泛型对象在C++中访问,因此创建上面的委托方法是可行的。

C++中的列表对象list

下面看看完整的C++/CLI反射调用的代码:

 std::list<CppUserInfo> GetUsers(String^ likeName)
 {
 //调用.NET方法,得到结果
 MethodInfo^ method = dotnetObject->GetType()->GetMethod("GetUsers", BindingFlags::Public | BindingFlags::Instance);
 Func<String^, IEnumerable^>^ fun = (Func<String^, IEnumerable^>^)Delegate::CreateDelegate(Func<String^, IEnumerable^>::typeid, 
 this->dotnetObject, method);
 IEnumerable^ result = fun(likeName);
 std::list<CppUserInfo> cppResult;
 for each (Object^ item in result)
 {
 Func<String^, Object^>^ entityProp = EntityHelper::EntityCallDelegate(item);
 CppUserInfo user;
 user.ID = (int)entityProp("ID");
 user.Name = (String^)entityProp("Name");
 user.Birthday = Convert2CppDateTime((DateTime^)entityProp("Birthday"));
 cppResult.push_back(user);
 }
 return cppResult;
 }
</div>

在C++中,常常使用 list来表示一个列表数据,例如上面方法中的代码:

std::list<CppUserInfo> cppResult;
</div>

为此C++需要包含以下头文件:

#include <list>
</div>

 要将一个对象添加到列表结尾,像下面这样调用即可:

cppResult.push_back(user);
</div>

在上一篇中已经讲述了如何从.NET对象转换给C++本地结构体,所以这个转换代码可以直接拿来用,综合起来,要从.NET集合得到C++的列表对象,像下面这样使用:

std::list<CppUserInfo> cppResult;
 for each (Object^ item in result)
 {
 Func<String^, Object^>^ entityProp = EntityHelper::EntityCallDelegate(item);
 CppUserInfo user;
 user.ID = (int)entityProp("ID");
 user.Name = (String^)entityProp("Name");
 user.Birthday = Convert2CppDateTime((DateTime^)entityProp("Birthday"));
 cppResult.push_back(user);
 }
</div>

 C++传递集合数据给.NET

前面讲了从.NET反射调用获得一个集合,看起来比较容易,但是从C++反射调用时候传递一个集合就不容易了。注意,这里传递的还是.NET的集合,所以这里需要做3件事情:

1,首先构建一个.NET集合对象;

2,转换C++本机结构数据到.NET集合元素;

3,反射调用.NET方法,传递数据过去。

先看要反射调用的.NET方法定义:

 public bool SaveUsers(IList<IUserInfo> users)
 {
 UserDb.AddRange(users);
 return true;
 }
</div>

方法非常简单,没有什么业务逻辑,接受一个列表接口的数据,然后返回一个布尔值。

在C++端看来,SaveUsers方法的参数对象是一个泛型集合,但是具体是什么对象并不知道,所以需要反射出泛型集合的类型,同时还需要构建这样一个泛型集合对象实例。

在本例中,要得到IUserInfo 这个泛型集合的类型,可以通过下面的代码:

MethodInfo^ method = dotnetObject->GetType()->GetMethod("SaveUsers", BindingFlags::Public | BindingFlags::Instance);
array<ParameterInfo^>^ pars = method->GetParameters();
Type^ paraType= pars[0]->ParameterType;
Type^ interfaceType = paraType->GetGenericArguments()[0];
</div>

注意上面的代码中使用了C++/CLI的数组类型 array<Type^>^ ,而不是C++标准库的数组,因此不要引用下面的命名空间:

using namespace std;
</div>

否则VS会提示数组定义缺少参数。

创建泛型List实例

我们使用List来做集合对象,在C#中,我们可以通过下面的方式得到List泛型的类型,然后进一步创建泛型对象实例:

Type t= typeof(List<>);
</div>

但是,对应的C++/CLI写法却无法通过编译:

Type^ t=List<>::typeid;
</div>

VS总是提示List缺少类型参数,不过像下面这样子是可以的:

Type^ t2= List<IUserInfo>::typeid;
</div>

但是IUserInfo 类型正是我们要动态反射的,事先并不知道,所以一时不知道在C++/CLI中如何构建List泛型的具体实例,MS你不能这么坑好么?

既然无法直接解决,只好曲线救国了,通过类型名字,来创建类型:

 String^ listTypeName = System::String::Format("System.Collections.Generic.List`1[{0}]", interfaceType->FullName);
</div>

可惜,这种方式不成功,只好一步步来了,先创建基本的List泛型类型:

 String^ listTypeName = "System.Collections.Generic.List`1";
 Type^ listType = System::Type::GetType(listTypeName);
</div>

成功,在此基础上,创建真正的泛型List对象实例就可以了,完整代码如下:

static Type^ CreateGenericListType(Type^ interfaceType)
 {
 //直接这样创建泛型List不成功:
 // String^ listTypeName = System::String::Format("System.Collections.Generic.List`1[{0}]", interfaceType->FullName);
 String^ listTypeName = "System.Collections.Generic.List`1";
 Type^ listType = System::Type::GetType(listTypeName);
 Type^ generListType = listType->MakeGenericType(interfaceType);
 return generListType;
 }
 static IList^ CreateGenericList(Type^ interfaceType)
 {
 Type^ generListType = CreateGenericListType(interfaceType);
 Object^ listObj = System::Activator::CreateInstance(generListType, nullptr);
 IList^ realList = (IList^)listObj;
 return realList;
 }
</div>

在方法 CreateGenericListType得到只是一个泛型List的类型,但我们并不知道这个List具体的形参类型,所以这个泛型List还是无法直接使用,幸好,泛型List也是继承自非泛型的IList接口的,所以在 CreateGeneri

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 在C++中反射调用.NET的方法(一)
  • 在C++中反射调用.NET的方法(二)
  • 在C++中反射调用.NET的方法(三)

相关文章

  • 2017-05-28深入c语言continue和break的区别详解
  • 2017-05-28MFC自定义消息的实现方法
  • 2017-05-28深入解析C语言中的内存分配相关问题
  • 2017-05-28深入解析C++设计模式编程中解释器模式的运用
  • 2017-05-28C语言 数据结构中求解迷宫问题实现方法
  • 2017-05-28C#委托所蕴含的函数指针概念详细解析
  • 2017-05-28详谈全排列next_permutation() 函数的用法(推荐)
  • 2017-05-28c语言与c++基础知识点(必看)
  • 2017-05-28C/C++: Inline function, calloc 对比 malloc
  • 2017-05-28C++设计模式之简单工厂模式实例

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 深入uCOS中全局变量的使用详解
    • MFC绘制不规则窗体的方法
    • C和指针小结(推荐)
    • 浅谈C语言的字符串分割
    • 详解C语言gets()函数与它的替代者fgets()函数
    • C++ operator关键字(重载操作符)的用法详解
    • 浅谈c++构造函数问题,初始化和赋值问题
    • 深入linux下遍历目录树的方法总结分析
    • c语言与c++基础知识点(必看)
    • C++中const的用法详细总结

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有