反射调用返回复杂对象的.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;
}
其中 IUserInfo是一个用户信息接口:
using System;
namespace NetLib
{
public interface IUserInfo
{
DateTime Birthday { get; set; }
int ID { get; set; }
string Name { get; set; }
}
}
接口内容很简单,有int,string,DateTime三种类型的属性,所以可以把它当做.NET与C++传递数据的DTO对象接口。
在方法 GetUserByID 中,有一行代码:
IUserInfo userinfo= EntityBuilder.CreateEntity<IUserInfo>();
EntityBuilder对象是PDF.NET SOD框架中的一个实体构造器,调用CreateEntity方法可以根据一个接口创建一个动态实体类对象,通过这种方式,我们可以不用去关心实体类的构造细节,仅仅关心方法调用的数据接口。在后面的示例中,我们都会通过这种接口对象的方式来传递数据。
绑定委托方法
下面我们来看看如何在C++/CLI中反射调用GetUserByID 这个方法。
虽然方法返回的是IUserInfo,但是对于我们的C++程序端来说,它并不知道IUserInfo这个接口对象,因为此接口没有在C++程序端定义,C++程序也没用引用它所在的.NET程序集,所以我们在反射调用GetUserByID 方法的时候,只能使用“弱类型”的Object,幸运的是我们调用的是返回值,而不是参数(反过来就不行,后面会有介绍),创建下面的委托对象是合法的:
Func<int, Object> fun;
详细的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;
}










