小編給大家分享一下在C++中如何反射調(diào)用.NET,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
成都創(chuàng)新互聯(lián)公司專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、鹽都網(wǎng)絡(luò)推廣、微信平臺(tái)小程序開發(fā)、鹽都網(wǎng)絡(luò)營銷、鹽都企業(yè)策劃、鹽都品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);成都創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供鹽都建站搭建服務(wù),24小時(shí)服務(wù)熱線:18980820575,官方網(wǎng)址:jinyejixie.com
為什么要在C++中調(diào)用.NET
一般情況下,我們常常會(huì)在.NET程序中調(diào)用C/C++的程序,使用P/Invoke方式進(jìn)行調(diào)用,在編寫代碼代碼的時(shí)候,首先要導(dǎo)入DLL文件,然后在根據(jù)C/C++的頭文件編寫特殊的C#平臺(tái)調(diào)用代碼,例如像下面這個(gè)樣子:
[DllImport("Interop.dll",EntryPoint = "Multiply",CharSet = CharSet.Ansi)] static extern int Multiply(int factorA, int factorB);
詳細(xì)的過程,可以參考之前我這篇文章:《C#調(diào)用C和C++函數(shù)的一點(diǎn)區(qū)別》
有時(shí)候,我們也會(huì)有在C++中調(diào)用.NET的需求,比如我們?cè)诰S護(hù)一個(gè)大型的C++應(yīng)用程序,它年代久遠(yuǎn),現(xiàn)在需要增加一些新功能,而這些功能在.NET中已經(jīng)有了,只需要調(diào)用它即可,如果為了方便想要用.NET重寫這個(gè)C++應(yīng)用程序是不太現(xiàn)實(shí)的,幸好,C++/CLI提供了一個(gè)簡(jiǎn)便的方案使得可以在C++中直接編寫.NET程序,所以C++/CLI代表托管和本地編程的結(jié)合,可以在托管代碼中直接使用本地代碼,也可以反過來,這樣結(jié)合了C++本地代碼的高效性和.NET代碼的強(qiáng)大性,看起來是非常有潛力的。
使用C++/CLI進(jìn)行.NET編程
要進(jìn)行C++/CLI編程,只需要進(jìn)行下面的步驟:
1,添加.NET程序集的應(yīng)用;
2,修改C++項(xiàng)目屬性,配置屬性->公共語言運(yùn)行時(shí)支持-公共語言運(yùn)行時(shí)支持(/clr)
然而,為了保持C++與.NET應(yīng)用程序的獨(dú)立性,要求不能將.NET的DLL文件放到C++的應(yīng)用程序目錄下,因此上述步驟1不可行,需要在C++代碼中使用反射來調(diào)用.NET。
注意,本文說的C++反射調(diào)用,不是對(duì)C++自身進(jìn)行封裝的反射功能,而是在C++/CLI代碼中反射調(diào)用.NET代碼,原理上跟你在.NET應(yīng)用中反射調(diào)用另外一個(gè).NET的程序集一個(gè)道理。
首先,我們建立一個(gè)名字叫CppNetTest的解決方案,添加3個(gè)項(xiàng)目:
1,CppConsoleTest---一個(gè)C++控制臺(tái)項(xiàng)目,在項(xiàng)目中更改屬性支持CLR;
2,NetApp--一個(gè).NET控制臺(tái)應(yīng)用程序,作為對(duì)比示例代碼,方便編寫C++/CLI代碼參考;
3,NetLib--一個(gè).NET類庫程序集,它將被1和2項(xiàng)目進(jìn)行反射調(diào)用。
我們先在NetLib項(xiàng)目寫一個(gè)簡(jiǎn)單的.NET 類,這個(gè)類的方法內(nèi)部沒有復(fù)雜的業(yè)務(wù)邏輯代碼,僅僅用來供反射調(diào)用測(cè)試:
namespace NetLib { public class User { static List<IUserInfo> UserDb = new List<IUserInfo>(); public int GetUserID(string IdString) { int result = 0; int.TryParse(IdString, out result); return result; } public DateTime GetUserBirthday(int userId) { return new DateTime(1980, 1, 1); } 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; } //返回List或者數(shù)組,不影響 C++調(diào)用 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 bool SaveUsers(IList<IUserInfo> users) { UserDb.AddRange(users); return true; } public IUserInfo CreateUserObject() { return EntityBuilder.CreateEntity<IUserInfo>(); } public bool SaveUsers2(IEnumerable<Object> para) { var users = from u in para select u as IUserInfo; return SaveUsers (users.ToList()); } } }
在CppConsoleTest項(xiàng)目的頭文件中,添加一個(gè) UserProxy.h 的C++頭文件,在文件中添加下面的命名空間:
using namespace System; using namespace System::Reflection; using namespace Runtime::InteropServices; using namespace System::Collections;
這樣我們就可以使用反射相關(guān)的類型了。
在UserProxy類中,先編寫我們需要的構(gòu)造函數(shù):
public ref class UserProxy { private: String^ assemblyFile; //"..\\NetLib\\bin\\Debug\\NetLib.dll" Object^ dotnetObject; Type^ entityBuilderType; String^ className = "NetLib.User"; EntityHelper^ helper; public: UserProxy(String^ assemblyFile) { this->assemblyFile = assemblyFile; Assembly^ ass = Assembly::LoadFrom(this->assemblyFile); this->dotnetObject = ass->CreateInstance(className); String^ sodPath = System::IO::Path::Combine(System::IO::Path::GetDirectoryName(this->assemblyFile), "PWMIS.Core.dll"); /*Assembly^ ass_sod = Assembly::LoadFrom(sodPath); this->entityBuilderType = ass_sod->GetType("PWMIS.DataMap.Entity.EntityBuilder");*/ helper = gcnew EntityHelper(sodPath); } }
注意我們的 C++/CLI的類必須是“引用”類型,所以需要加關(guān)鍵字 ref,即:
public ref class UserProxy{}
所有的.NET引用類型,在使用的時(shí)候,都必須在類型名字后加 ^ 符號(hào),例如下面定一個(gè).NET字符串類型變量:
String^ assemblyFile;
帶^符號(hào)的變量,在C++/CLI中稱為 “句柄”對(duì)象,用來跟C++本地代碼的“指針”相區(qū)別。
在C++中,類的成員用 -> 符號(hào)調(diào)用,命名空間或者類的靜態(tài)成員,用::調(diào)用,例如上面的構(gòu)造函數(shù)中的代碼:
Assembly^ ass = Assembly::LoadFrom(this->assemblyFile);
注意:在本例中需要.NET類庫項(xiàng)目引用 PDF.NET SOD框架,在項(xiàng)目的“管理Nuget程序包”里面搜索 PDF.NET.SOD.Core 添加此引用即可。
學(xué)會(huì)了這些C++的基礎(chǔ)語法,那么編寫C++/CLI代碼就沒有主要的障礙了。
在C++/CLI中使用反射
反射調(diào)用第一個(gè).NET類的方法
下面的方法,將會(huì)反射調(diào)用 User類的一個(gè)最簡(jiǎn)單的方法 :
public int GetUserID(string IdString){}
該方法只有一個(gè)一個(gè)參數(shù)和一個(gè)簡(jiǎn)單的返回值,下面是C++/CLI的反射調(diào)用代碼:
int GetUserID(String^ iDstring) { MethodInfo^ method = this->dotnetObject->GetType()->GetMethod("GetUserID", BindingFlags::Public | BindingFlags::Instance); Func<String^, int>^ fun = (Func<String^, int>^)Delegate::CreateDelegate(Func<String^, int>::typeid, this->dotnetObject, method); int result = fun(iDstring); return result; }
注意這里創(chuàng)建了一個(gè) Func<String,int>的委托方法,使用委托能夠簡(jiǎn)化我們的反射調(diào)用并且有時(shí)候還能夠提高效率,在這段代碼中,有1個(gè)要注意的地方:
Func<String^, int>::typeid
這是C++/CLI特殊的語法,表示獲取“句柄”類型的類型ID,實(shí)際上它的結(jié)果就Type對(duì)象,等同于C#的typeof(Func<string,int>)
PS:非常遺憾的是,typeid方式,沒法得到下面類型的類型值:
typeof(Func<,>),這給我們?cè)趧?dòng)態(tài)構(gòu)造泛型對(duì)象的時(shí)候造成了很大的困惑。
再看一個(gè)簡(jiǎn)單方法的反射:
DateTime GetUserBirthday(int userId) { MethodInfo^ method = dotnetObject->GetType()->GetMethod("GetUserBirthday", BindingFlags::Public | BindingFlags::Instance); Func<int, DateTime>^ fun = (Func<int, DateTime>^)Delegate::CreateDelegate(Func<int, DateTime>::typeid, this->dotnetObject, method); DateTime result = fun(userId); return result; }
注意:由于DateTime是值類型,因此在進(jìn)行類型申明的時(shí)候,不需要加^符號(hào),僅需要對(duì)Func委托加上^句柄標(biāo)記。
有了這2個(gè)簡(jiǎn)單的方法,我們來看看如何調(diào)用這個(gè).NET方法“代理類”:
NetLibProxy::UserProxy^ proxy = gcnew NetLibProxy::UserProxy("..\\NetLib\\bin\\Debug\\NetLib.dll"); int result= proxy->GetUserID("123456"); DateTime date = proxy->GetUserBirthday(result); System::Console::WriteLine("C++/CLI .Net Proxy Class Call Test Result:\r\n UserID={0},\r\n Birthday={1}", result,date.ToShortDateString());
OK,第一個(gè)C++/CLI代碼調(diào)用成功,而且還是反射調(diào)用的,心情小激動(dòng)一下。
以上是“在C++中如何反射調(diào)用.NET”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
分享題目:在C++中如何反射調(diào)用.NET
鏈接分享:http://jinyejixie.com/article34/gdpdpe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航、外貿(mào)建站、企業(yè)網(wǎng)站制作、網(wǎng)頁設(shè)計(jì)公司、Google、網(wǎng)站維護(hù)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)