The call is reflected in C + +. NET (ii)

Source: Internet
Author: User

The reflection call returns a complex object. Net method defines the data interface

The previous article reflects the call in C + +. NET (i), we briefly describe how to use C + +/CLI and initially use a simple method of reflection calling. NET assemblies, today we look at how to pass complex objects between C + + and. NET assemblies.

Look first. NET assembly is a way to return an object:

 Public Iuserinfo Getuserbyid (int  userId)        {            iuserinfo userinfo= entitybuilder.createentity< Iuserinfo>();             = userId;             " Name _ " + userId;             New DateTime (198011);             return userinfo;        }

Where Iuserinfo is a user information interface:

using System; namespace netlib{    publicinterface  iuserinfo    {        getSet ; }         int Get Set ; }         string Get Set ; }    }}

The interface content is simple, there are int,string,datetime three types of attributes, so it can be considered as. NET and C + + to pass data to the Dto object interface.

In method Getuserbyid, there is a line of code:

Iuserinfo userinfo= entitybuilder.createentity<iuserinfo> ();

The Entitybuilder object is an entity constructor in the pdf.net sod frame, which calls the Createentity method to create a dynamic entity class object based on an interface, so that we can not care about the construction details of the entity class. Just care about the data interface of the method invocation. In the following example, we will pass the data through this interface object.

Binding Delegate Method

Let's take a look at how to reflect the call Getuserbyid in C + +/CLI.
Although the method returns Iuserinfo, for our C + + terminal, it does not know iuserinfo this interface object, because this interface is not defined in the C + + terminal, C + + programs do not reference it. NET assembly, so we can only use "weakly typed" object when reflection calls the Getuserbyid method, fortunately we call the return value instead of the parameter (which, in turn, is not possible, as described later), and it is legal to create the following delegate object:

func<int, object> fun;

Detailed C + +/CLI reflection code is as follows:

Cppuserinfo Getuserbyid (intuserId) {            //called. net method to get resultsmethodinfo^ method = Dotnetobject->gettype ()->getmethod ("Getuserbyid", BindingFlags::P ublic |bindingflags::instance); Func<int, object^>^ fun = (func<int, object^>^) delegate::createdelegate (func<int, Object^>::typeid, This-Dotnetobject, method); Object^ result =Fun (userId); //Convert managed type data to native structfunc<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")); returnuser; }

In the preceding code, it is called by a delegate method:

object^ result = Fun (userId);
Using the Sod DTO object

We got it. NET assembly method returns the Dto object, but how do I take out its data to assign to our C + + native code?
So here are 2 questions to be addressed:
1. Remove data from object objects;
2, converting and assigning data to C + + Local data structures

For the first question, we can reflect the properties of the Dto object and then correspond to the local data interface one by one, but we've already called the method in reflection, and it's complicated to reflect again.
Fortunately, our DTO interface object It is a dynamically created sod entity class object, because the sod entity class has the function of similar "dictionary", can be accessed by relevant method.

A method definition for the entity class base class:

 Public Object PropertyList (string propertyfieldname)

We reflect this method and bind a delegate object to invoke it:

        Staticfunc<string^, object^>^ entitycalldelegate (object^entity) {            //a method definition for the entity class base class://Public Object PropertyList (string propertyfieldname)type^Base= Entity->gettype ()BaseType; MethodInfo^ Methodentity =Base->getmethod ("propertylist", BindingFlags::P ublic |bindingflags::instance); Func<string^, object^>^ funentity = (func<string^, object^>^) delegate::createdelegate (Func<String^, Object^>:: typeID,
entity, methodentity); //example string^ result = (string^) funentity ("Name"); returnfunentity; }

Then, you can use the following as follows:

func<string^, object^>^ entityprop =entityhelper::entitycalldelegate (result); int id = (int) entityprop ("ID");
To convert a. NET object to a C + + struct

In the example, we define a cppuserinfo struct:

struct cppuserinfo{    int  ID;     // wstring Name;     CString Name;    TM Birthday;};
Managed string vs. native string

This structure corresponds to the C # version of the interface Iuserinfo, but the struct members have several points to note:

CString Name;

The string type's name member, to use the string type in C + +, must contain the following header file in the C + + file:
If it is not an MFC application, include the following:

#include <atlstr.h>

Otherwise, this header file needs to be included:

#include <cstringt.h>

If you are not using CString, but wstring, then you need to define a method to implement the conversion of a managed string to a native string:

     //     // to use the following method, first  #include <string>     //    static wstring marshalstring (string ^ s) {        wstring os;         Const wchar_t* chars =            (const wchar_t*) (Marshal::stringtohglobaluni (s)) . ToPointer ();         = chars;        Marshal::freehglobal (IntPtr ((void*) chars));         return os;    }

The above method declares a pointer of type wchar_t*, which must be freed by this pointer at the end of the method, so this form of conversion is still more cumbersome.
For a managed string conversion to a C + + native string, refer to the following 2 articles:

http://bbs.csdn.net/topics/280024331

http://blog.csdn.net/windren06/article/details/7839985

Managed date and native date data

The struct that represents the date in C + + is a TM, but it is important to note that the year portion of the TM is only able to represent the difference from 1900, so we can write the following 2 methods for a simple conversion:

 static  TM Convert2cppdatetime (Datetime^        DT) {TM result;        Result.tm_year  = dt->year-1900   = Dt->month;        Result.tm_wday  = Dt->day;     return   result;  static  datetime^ Covert2netdatetime (            TM cppdate) { return   gcnew DateTime ( Cppdate.tm_year  + 1900  , CP    Pdate.tm_mon, Cppdate.tm_wday); }

With a string followed by a date type. NET and C + + conversion, basically can be used. NET DTO objects, because other numeric types can be used directly, such as the int type, as long as the type is compatible.

Converting to a native struct

Here's another look at the Object Data Transformation section within the Getuserbyid method:

 //  convert managed type data to native structure  func<string^            , object^>^ entityprop =entityhelper::entitycalldelegate (Result);            Cppuserinfo user; User.ID  = ("  Span style= "color: #800000;"            >id   ); User. Name  = (string^) entityprop ( name  ); //             Marshalstring ((string^) entityprop (" Name ");  User. Birthday = Convert2cppdatetime ((datetime^) entityprop ( " birthday  )); 

Now look again, using similar "dictionary" access to the Sod Dto object, to the C + + local structure conversion assignment data, it is very convenient, this is the choice of the SOD framework as C + + and. NET communication reasons.

Why not use serialization issues

In a distributed cross-platform invocation, serialization is often used as an effective means, but our application has several features:
1, there is no distributed, in the process of different language platform calls;
2, the type of deserialization is not known, because C + + does not directly reference any. NET Framework itself. NET assemblies;
3, serialization requires the use of reflection, and we are already in the reflection, will aggravate the burden;

In addition, the use of serialization also has additional work:
4, using serialization requires additional encapsulation by the called side;
5, both sides need to develop common communication protocols, and customize the serialization process, such as the common RPC framework conventions of the serialization Protocol

So, after careful consideration, I abandoned the idea of using serialization to do in-process communication with. NET in C + +.

In the next article, we'll show you how C + + and. NET Pass Collection objects.
(not to be continued)

The call is reflected in C + +. NET (ii)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.