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

—-想了解在C++中反射调用.NET的方法(一)分享的全部内容且更多的C语言教程关注<计算机技术网>

为什么要在C++中调用.NET

一般情况下,我们常常会在.NET程序中调用C/C++的程序,使用P/Invoke方式进行调用,在编写代码代码的时候,首先要导入DLL文件,然后在根据C/C++的头文件编写特殊的C#平台调用代码,例如像下面这个样子:

   [DllImport("Interop.dll",EntryPoint = "Multiply",CharSet = CharSet.Ansi)]   static extern int Multiply(int factorA, int factorB);

详细的过程,可以参考之前我这篇文章:《C#调用C和C++函数的一点区别》

有时候,我们也会有在C++中调用.NET的需求,比如我们在维护一个大型的C++应用程序,它年代久远,现在需要增加一些新功能,而这些功能在.NET中已经有了,只需要调用它即可,如果为了方便想要用.NET重写这个C++应用程序是不太现实的,幸好,C++/CLI提供了一个简便的方案使得可以在C++中直接编写.NET程序,所以C++/CLI代表托管和本地编程的结合,可以在托管代码中直接使用本地代码,也可以反过来,这样结合了C++本地代码的高效性和.NET代码的强大性,看起来是非常有潜力的。

使用C++/CLI进行.NET编程

要进行C++/CLI编程,只需要进行下面的步骤:

1,添加.NET程序集的应用;

2,修改C++项目属性,配置属性->公共语言运行时支持-公共语言运行时支持(/clr)

然而,为了保持C++与.NET应用程序的独立性,要求不能将.NET的DLL文件放到C++的应用程序目录下,因此上述步骤1不可行,需要在C++代码中使用反射来调用.NET。

注意,在C++中反射调用.NET的方法(一)分享说的C++反射调用,不是对C++自身进行封装的反射功能,而是在C++/CLI代码中反射调用.NET代码,原理上跟你在.NET应用中反射调用另外一个.NET的程序集一个道理。

首先,我们建立一个名字叫CppNetTest的解决方案,添加3个项目:

1,CppConsoleTest—一个C++控制台项目,在项目中更改属性支持CLR;

2,NetApp–一个.NET控制台应用程序,作为对比示例代码,方便编写C++/CLI代码参考;

3,NetLib–一个.NET类库程序集,它将被1和2项目进行反射调用。

我们先在NetLib项目写一个简单的.NET 类,这个类的方法内部没有复杂的业务逻辑代码,仅仅用来供反射调用测试:

  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或者数组,不影响 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 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项目的头文件中,添加一个 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; //"..\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的类必须是“引用”类型,所以需要加关键字 ref,即:

  public ref class UserProxy{}

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请点击右边联系管理员删除。

如若转载,请注明出处:https://www.ctvol.com/c-cdevelopment/487831.html

(0)
上一篇 2020年11月12日
下一篇 2020年11月12日

精彩推荐