• 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++中反射调用.NET(一)中,我们简单的介绍了如何使用C++/CLI并且初步使用了反射调用.NET程序集的简单方法,今天我们看看如何在C++与.NET程序集之间传递复杂对象。

先看看.NET程序集的一个返回对象的方法:

 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>

其中 IUserInfo是一个用户信息接口:

using System;
namespace NetLib
{
 public interface IUserInfo
 {
 DateTime Birthday { get; set; }
 int ID { get; set; }
 string Name { get; set; }
 }
}
</div>

接口内容很简单,有int,string,DateTime三种类型的属性,所以可以把它当做.NET与C++传递数据的DTO对象接口。

在方法 GetUserByID 中,有一行代码:

IUserInfo userinfo= EntityBuilder.CreateEntity<IUserInfo>();
</div>

EntityBuilder对象是PDF.NET SOD框架中的一个实体构造器,调用CreateEntity方法可以根据一个接口创建一个动态实体类对象,通过这种方式,我们可以不用去关心实体类的构造细节,仅仅关心方法调用的数据接口。在后面的示例中,我们都会通过这种接口对象的方式来传递数据。

绑定委托方法

下面我们来看看如何在C++/CLI中反射调用GetUserByID 这个方法。

虽然方法返回的是IUserInfo,但是对于我们的C++程序端来说,它并不知道IUserInfo这个接口对象,因为此接口没有在C++程序端定义,C++程序也没用引用它所在的.NET程序集,所以我们在反射调用GetUserByID 方法的时候,只能使用“弱类型”的Object,幸运的是我们调用的是返回值,而不是参数(反过来就不行,后面会有介绍),创建下面的委托对象是合法的:

Func<int, Object> fun;
</div>

详细的C++/CLI反射代码如下:

CppUserInfo GetUserByID(int userId)
 {
  //调用.NET方法,得到结果
  MethodInfo^ method = dotnetObject->GetType()->GetMethod("GetUserByID", BindingFlags::Public | BindingFlags::Instance);
  Func<int, Object^>^ fun = (Func<int, Object^>^)Delegate::CreateDelegate(Func<int, Object^>::typeid, this->dotnetObject, method);
  Object^ result = fun(userId);
  //转换托管类型数据到本机结构体
  Func<String^, Object^>^ entityProp =EntityHelper::EntityCallDelegate(result);
  CppUserInfo user;
  user.ID = (int)entityProp("ID");
  user.Name = (String^)entityProp("Name");// MarshalString((String^)entityProp("Name"));
  user.Birthday = Convert2CppDateTime((DateTime^)entityProp("Birthday"));
  return user;
 }
</div>

在上面的代码中,通过委托方法调用:

Object^ result = fun(userId); 
</div>

使用SOD DTO 对象

我们得到了.NET程序集的方法返回的DTO对象,但是如何取出它的数据赋值给我们的C++本机代码呢?

所以这里涉及到2个问题:

1,从Object对象取出数据;

2,将数据转换并且赋值给C++本地数据结构

对于第一个问题,我们可以反射DTO对象的属性,然后跟本地数据接口一一对应,但是,本来我们已经在反射调用方法了,再来一次反射事情就复杂了。

幸好,我们的DTO接口对象它是一个动态创建的SOD实体类对象,由于SOD实体类有类似“字典”的功能,可以通过相关方法进行访问。

实体类基类的一个方法定义:

public object PropertyList(string propertyFieldName)
</div>

我们反射此方法并且绑定一个委托对象来调用它:

 static Func<String^, Object^>^ EntityCallDelegate(Object^ entity)
 {
  //实体类基类的一个方法定义:
  //public object PropertyList(string propertyFieldName)
  Type^ base = entity->GetType()->BaseType;
  MethodInfo^ methodEntity = base->GetMethod("PropertyList", BindingFlags::Public | BindingFlags::Instance);
  Func<String^, Object^>^ funEntity = (Func<String^, Object^>^)Delegate::CreateDelegate(Func<String^, Object^>::typeid, 
      entity, methodEntity);
  //示例 String^ result = (String^)funEntity("Name");
  return funEntity;
 }
</div>

然后,就能像下面这样使用了:

Func<String^, Object^>^ entityProp =EntityHelper::EntityCallDelegate(result);
int id = (int)entityProp("ID");
</div>

将.NET对象转换到C++结构体

在示例中,我们定义了一个CppUserInfo结构体:

struct CppUserInfo
{
 int ID;
 //wstring Name;
 CString Name;
 tm Birthday;
};
</div>

托管字符串与本机字符串

这个结构体跟C#版本的接口 IUserInfo对应,但是结构体成员有几个需要注意的地方:

CString Name;

字符串类型的“名字”成员,要在C++中使用字符串类型,必须在C++文件中包含下面的头文件:
如果不是 MFC应用程序,包含下面这个:

#include <atlstr.h>

否则,需要包含这个头文件:

#include <cstringt.h>  

如果不是使用CString,而是 wstring,那么需要定义一个方法来实现托管字符串到本机字符串的转换: 

// 
 //要使用下面的方法,请先 #include <string> 
 //
 static wstring MarshalString(String ^ s) {
  wstring os;
  const wchar_t* chars =
   (const wchar_t*)(Marshal::StringToHGlobalUni(s)).ToPointer();
  os = chars;
  Marshal::FreeHGlobal(IntPtr((void*)chars));
  return os;
 }
</div>

上面的方法申明了一个 wchar_t* 类型的指针,在方法结尾必须释放此指针占用的内存,所以这种形式的转换还是比较麻烦。
有关托管字符串跟C++本机字符串的转换。

托管日期与本机日期数据

在C++中表示日期的结构体是 tm,但是需要注意的是 tm的year部分仅能够表示与1900的差值,所以我们可以写下面2个方法来简单的转换:

 static tm Convert2CppDateTime(DateTime^ dt)
 {
  tm result;
  result.tm_year = dt->Year - 1900;
  result.tm_mon = dt->Month;
  result.tm_wday = dt->Day;
  return result;
 }
 static DateTime^ Covert2NetDateTime(tm cppDate)
 {
  return gcnew DateTime(
   cppDate.tm_year + 1900, 
   cppDate.tm_mon, 
   cppDate.tm_wday
  );
 }
</div>

有了字符串跟日期类型的.NET与C++的相互转换,基本上就能够使用.NET的DTO对象了,因为其它数字类型只要类型兼容,是可以直接使用的,比如int类型。

转换到本机结构体

下面再回来看看 GetUserByID 方法内的对象数据转换部分:

//转换托管类型数据到本机结构体
   Func<String^, Object^>^ entityProp =EntityHelper::EntityCallDelegate(result);
   CppUserInfo user;
   user.ID = (int)entityProp("ID");
   user.Name = (String^)entityProp("Name");// MarshalString((String^)entityProp("Name"));
   user.Birthday = Convert2CppDateTime((DateTime^)entityProp("Birthday"));
</div>

现在再看看,采用类似“字典”访问方式的SOD DTO对象,给C++本地结构体转换赋值数据,就很方便了,这也是本篇选择SOD框架作为C++与.NET通信的原因了。

为何不使用序列化的问题

在进行分布式跨平台调用的时候,序列化常常作为一个有效手段被大量使用,但是我们的应用有几个特点:

1,没有分布式

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

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

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

相关文章

  • 2017-05-28libevent库的使用方法实例
  • 2017-05-28C++开发的Redis数据导入工具优化
  • 2017-05-28高效实现整型数字转字符串int2str的方法
  • 2017-05-28一波C语言二元查找树算法题目解答实例汇总
  • 2017-05-28构造函数定义为private或者protected的好处
  • 2017-05-28深入解析C语言中typedef的四个用途
  • 2017-05-28详解C++编程中类模板的相关使用知识
  • 2017-05-28c++中数字与字符串之间的转换方法(推荐)
  • 2017-05-28C++无法重载点符号、::、sizeof等的原因
  • 2017-05-28详解C语言中strpbrk()函数的用法

文章分类

  • 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语言中结构体struct编写的一些要点解析
    • 基于C语言实现的迷宫游戏代码
    • C++ 基础编程之十进制转换为任意进制及操作符重载
    • C++11新特性之auto的使用
    • 解析C++编程中的#include和条件编译
    • C语言关键字大全(共32个)
    • 深入解析Radix Sort基数排序算法思想及C语言实现示例
    • 深入解析C++中派生类的构造函数

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

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