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

2020-01-06 16:41:57王旭

在CppConsoleTest项目的头文件中,添加一个 UserProxy.h 的C++头文件,在文件中添加下面的命名空间:


using namespace System;
using namespace System::Reflection;
using namespace Runtime::InteropServices;
using namespace System::Collections;

这样我们就可以使用反射相关的类型了。

在UserProxy类中,先编写我们需要的构造函数:


public ref class UserProxy
  {
  private:
    String^ assemblyFile; //"..NetLibbinDebugNetLib.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的类必须是“引用”类型,所以需要加关键字 ref,即:


public ref class UserProxy{}

所有的.NET引用类型,在使用的时候,都必须在类型名字后加 ^ 符号,例如下面定一个.NET字符串类型变量:


String^ assemblyFile; 

带^符号的变量,在C++/CLI中称为 “句柄”对象,用来跟C++本地代码的“指针”相区别。

在C++中,类的成员用 -> 符号调用,命名空间或者类的静态成员,用::调用,例如上面的构造函数中的代码:


Assembly^ ass = Assembly::LoadFrom(this->assemblyFile);

 注意:在本例中需要.NET类库项目引用 PDF.NET SOD框架,在项目的“管理Nuget程序包”里面搜索 PDF.NET.SOD.Core 添加此引用即可。
学会了这些C++的基础语法,那么编写C++/CLI代码就没有主要的障碍了。

在C++/CLI中使用反射

反射调用第一个.NET类的方法

下面的方法,将会反射调用 User类的一个最简单的方法 :


public int GetUserID(string IdString){}

该方法只有一个一个参数和一个简单的返回值,下面是C++/CLI的反射调用代码:


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