欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

在C++中反射調(diào)用.NET的方法(二)

 更新時(shí)間:2017年02月05日 10:02:06   作者:深藍(lán)醫(yī)生  
反射調(diào)用返回復(fù)雜對(duì)象的.NET方法怎么實(shí)現(xiàn)呢?今天小編通過本文給大家分享在C++中反射調(diào)用.NET的方法(二),需要的朋友參考下

反射調(diào)用返回復(fù)雜對(duì)象的.NET方法

定義數(shù)據(jù)接口

上一篇在C++中反射調(diào)用.NET(一)中,我們簡單的介紹了如何使用C++/CLI并且初步使用了反射調(diào)用.NET程序集的簡單方法,今天我們看看如何在C++與.NET程序集之間傳遞復(fù)雜對(duì)象。

先看看.NET程序集的一個(gè)返回對(duì)象的方法:

 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;
 }

其中 IUserInfo是一個(gè)用戶信息接口:

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

接口內(nèi)容很簡單,有int,string,DateTime三種類型的屬性,所以可以把它當(dāng)做.NET與C++傳遞數(shù)據(jù)的DTO對(duì)象接口。

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

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

EntityBuilder對(duì)象是PDF.NET SOD框架中的一個(gè)實(shí)體構(gòu)造器,調(diào)用CreateEntity方法可以根據(jù)一個(gè)接口創(chuàng)建一個(gè)動(dòng)態(tài)實(shí)體類對(duì)象,通過這種方式,我們可以不用去關(guān)心實(shí)體類的構(gòu)造細(xì)節(jié),僅僅關(guān)心方法調(diào)用的數(shù)據(jù)接口。在后面的示例中,我們都會(huì)通過這種接口對(duì)象的方式來傳遞數(shù)據(jù)。

綁定委托方法

下面我們來看看如何在C++/CLI中反射調(diào)用GetUserByID 這個(gè)方法。

雖然方法返回的是IUserInfo,但是對(duì)于我們的C++程序端來說,它并不知道IUserInfo這個(gè)接口對(duì)象,因?yàn)榇私涌跊]有在C++程序端定義,C++程序也沒用引用它所在的.NET程序集,所以我們在反射調(diào)用GetUserByID 方法的時(shí)候,只能使用“弱類型”的Object,幸運(yùn)的是我們調(diào)用的是返回值,而不是參數(shù)(反過來就不行,后面會(huì)有介紹),創(chuàng)建下面的委托對(duì)象是合法的:

Func<int, Object> fun;

詳細(xì)的C++/CLI反射代碼如下:

CppUserInfo GetUserByID(int userId)
 {
  //調(diào)用.NET方法,得到結(jié)果
  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);
  //轉(zhuǎn)換托管類型數(shù)據(jù)到本機(jī)結(jié)構(gòu)體
  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;
 }

在上面的代碼中,通過委托方法調(diào)用:

Object^ result = fun(userId); 

使用SOD DTO 對(duì)象

我們得到了.NET程序集的方法返回的DTO對(duì)象,但是如何取出它的數(shù)據(jù)賦值給我們的C++本機(jī)代碼呢?

所以這里涉及到2個(gè)問題:

1,從Object對(duì)象取出數(shù)據(jù);

2,將數(shù)據(jù)轉(zhuǎn)換并且賦值給C++本地?cái)?shù)據(jù)結(jié)構(gòu)

對(duì)于第一個(gè)問題,我們可以反射DTO對(duì)象的屬性,然后跟本地?cái)?shù)據(jù)接口一一對(duì)應(yīng),但是,本來我們已經(jīng)在反射調(diào)用方法了,再來一次反射事情就復(fù)雜了。

幸好,我們的DTO接口對(duì)象它是一個(gè)動(dòng)態(tài)創(chuàng)建的SOD實(shí)體類對(duì)象,由于SOD實(shí)體類有類似“字典”的功能,可以通過相關(guān)方法進(jìn)行訪問。

實(shí)體類基類的一個(gè)方法定義:

public object PropertyList(string propertyFieldName)

我們反射此方法并且綁定一個(gè)委托對(duì)象來調(diào)用它:

 static Func<String^, Object^>^ EntityCallDelegate(Object^ entity)
 {
  //實(shí)體類基類的一個(gè)方法定義:
  //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;
 }

然后,就能像下面這樣使用了:

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

將.NET對(duì)象轉(zhuǎn)換到C++結(jié)構(gòu)體

在示例中,我們定義了一個(gè)CppUserInfo結(jié)構(gòu)體:

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

托管字符串與本機(jī)字符串

這個(gè)結(jié)構(gòu)體跟C#版本的接口 IUserInfo對(duì)應(yīng),但是結(jié)構(gòu)體成員有幾個(gè)需要注意的地方:

CString Name;

字符串類型的“名字”成員,要在C++中使用字符串類型,必須在C++文件中包含下面的頭文件:
如果不是 MFC應(yīng)用程序,包含下面這個(gè):

#include <atlstr.h>

否則,需要包含這個(gè)頭文件:

#include <cstringt.h>  

如果不是使用CString,而是 wstring,那么需要定義一個(gè)方法來實(shí)現(xiàn)托管字符串到本機(jī)字符串的轉(zhuǎn)換: 

// 
 //要使用下面的方法,請先 #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;
 }

上面的方法申明了一個(gè) wchar_t* 類型的指針,在方法結(jié)尾必須釋放此指針占用的內(nèi)存,所以這種形式的轉(zhuǎn)換還是比較麻煩。
有關(guān)托管字符串跟C++本機(jī)字符串的轉(zhuǎn)換。

托管日期與本機(jī)日期數(shù)據(jù)

在C++中表示日期的結(jié)構(gòu)體是 tm,但是需要注意的是 tm的year部分僅能夠表示與1900的差值,所以我們可以寫下面2個(gè)方法來簡單的轉(zhuǎn)換:

 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
  );
 }

有了字符串跟日期類型的.NET與C++的相互轉(zhuǎn)換,基本上就能夠使用.NET的DTO對(duì)象了,因?yàn)槠渌鼣?shù)字類型只要類型兼容,是可以直接使用的,比如int類型。

轉(zhuǎn)換到本機(jī)結(jié)構(gòu)體

下面再回來看看 GetUserByID 方法內(nèi)的對(duì)象數(shù)據(jù)轉(zhuǎn)換部分:

//轉(zhuǎn)換托管類型數(shù)據(jù)到本機(jī)結(jié)構(gòu)體
   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"));

現(xiàn)在再看看,采用類似“字典”訪問方式的SOD DTO對(duì)象,給C++本地結(jié)構(gòu)體轉(zhuǎn)換賦值數(shù)據(jù),就很方便了,這也是本篇選擇SOD框架作為C++與.NET通信的原因了。

為何不使用序列化的問題

在進(jìn)行分布式跨平臺(tái)調(diào)用的時(shí)候,序列化常常作為一個(gè)有效手段被大量使用,但是我們的應(yīng)用有幾個(gè)特點(diǎn):

1,沒有分布式,在進(jìn)程內(nèi)進(jìn)行不同語言平臺(tái)調(diào)用;

2,不知道反序列化的類型,因?yàn)镃++沒有直接引用任何.NET框架自身之外的.NET程序集;

3,序列化需要使用反射,而我們本來已經(jīng)在反射了,會(huì)加重負(fù)擔(dān);

除此之外,使用序列化還會(huì)有額外的工作:

4,使用序列化會(huì)要求被調(diào)用端進(jìn)行額外的封裝;

5,雙方需要制定通用的通信協(xié)議,并且定制序列化過程,比如常見RPC框架約定的序列化協(xié)議

所以,經(jīng)過仔細(xì)考慮后,放棄了使用序列化方式來進(jìn)行C++與.NET進(jìn)行進(jìn)程內(nèi)通信的想法。

以上所述是小編給大家介紹的在C++中反射調(diào)用.NET的方法(二),希望對(duì)大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會(huì)及時(shí)回復(fù)大家的!

相關(guān)文章

  • C/C++實(shí)現(xiàn)三路快速排序算法原理

    C/C++實(shí)現(xiàn)三路快速排序算法原理

    這篇文章主要為大家詳細(xì)介紹了C/C++實(shí)現(xiàn)三路快速排序算法原理,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • C語言scanf,fscanf和sscanf的區(qū)別

    C語言scanf,fscanf和sscanf的區(qū)別

    每種語言都對(duì)正則表達(dá)式有著不同程度的支持,在C語言中,有輸入功能的這三個(gè)函數(shù)對(duì)正則表達(dá)式的支持并不強(qiáng)大,但是我們還是有必要了解一下
    2021-10-10
  • Qt數(shù)據(jù)庫相關(guān)應(yīng)用開發(fā)總結(jié)

    Qt數(shù)據(jù)庫相關(guān)應(yīng)用開發(fā)總結(jié)

    這篇文章主要為大家介紹了在Qt數(shù)據(jù)庫應(yīng)用開發(fā)中的一些經(jīng)驗(yàn)總結(jié),以及一些組件的使用介紹。文中的示例代碼講解詳細(xì),需要的可以參考一下
    2022-02-02
  • Windows下sentry接入C/C++程序的詳細(xì)過程

    Windows下sentry接入C/C++程序的詳細(xì)過程

    sentry作為一個(gè)開源的軟件,發(fā)展至今,已經(jīng)非常成熟。它支持的平臺(tái)眾多,甚至于針對(duì)不同的工作者(后臺(tái)、前端、客戶端)都有相應(yīng)的內(nèi)容,這篇文章主要介紹了Windows下sentry接入C/C++程序,需要的朋友可以參考下
    2022-09-09
  • C語言實(shí)現(xiàn)簡單通訊錄功能

    C語言實(shí)現(xiàn)簡單通訊錄功能

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)簡單通訊錄功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • c++ 調(diào)用python傳輸圖片實(shí)例

    c++ 調(diào)用python傳輸圖片實(shí)例

    今天小編就為大家分享一篇c++ 調(diào)用python傳輸圖片實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • C++中的Lambda表達(dá)式詳解

    C++中的Lambda表達(dá)式詳解

    這篇文章主要介紹了C++中的Lambda表達(dá)式詳解,本文講解了基本語法、Lambda的使用等內(nèi)容,需要的朋友可以參考下
    2014-10-10
  • 探討C++中不能聲明為虛函數(shù)的有哪些函數(shù)

    探討C++中不能聲明為虛函數(shù)的有哪些函數(shù)

    下面小編就為大家?guī)硪黄接慍++中不能聲明為虛函數(shù)的有哪些函數(shù)。希望對(duì)大家有所幫助。一起跟隨小編過來看看吧,祝大家游戲愉快哦
    2017-01-01
  • 內(nèi)核線程優(yōu)先級(jí)設(shè)置的方法介紹

    內(nèi)核線程優(yōu)先級(jí)設(shè)置的方法介紹

    本篇文章介紹了,內(nèi)核線程優(yōu)先級(jí)設(shè)置的方法。需要的朋友參考下
    2013-05-05
  • 從零學(xué)習(xí)構(gòu)造系統(tǒng)之bazel示例詳解

    從零學(xué)習(xí)構(gòu)造系統(tǒng)之bazel示例詳解

    這篇文章主要為大家介紹了從零學(xué)習(xí)構(gòu)造系統(tǒng)之bazel示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02

最新評(píng)論