Yuck...
Look very carefully at your managed / native interface and figure out how to minimize this sort of thing.
I have a fairly complex system with a lot of native C++ that does a lot of computationaly intensive stuff and some C# user interface components (that are mostly some fancy 3rd party libraries that I couldn't buy in native format).
In one place I need to pass a fairly complex tree like structure from native C++ to C# -- what I decided was easiest was to create a parallel class in C# and then write a C++/CLR routine that basically copies the data from the native-C class to the equivalent managed-C# class.
I have one routine that copies from the native class to the managed class and one routine that copies from the managed class to the native class. I use that to pass all the data across the native / managed interface.
I do all the heavy computation stuff in the native side, covert it and pass it through to the managed UI, let the user manipulate it all he likes, then covert it and pass it back.
C++/CLR handles all the magic, I never write a single marshal statement.
If you find yourself writing Marshal or MarshalAs more than one or twice, it's time to review how things are split up and figure out a better division.
Assuming you have written a C# module called MyCSharpModule with classes CLRHouse and CLRRoom, then you can write a C++/CLR routine that looks something like this:
#using <MyCSharpModule.dll>
MyCSharpModule::CLRHouse ^ ToCLRHouse( CHouse *pHouse)
{
MyCSharpModule::CLRHouse ^newHouse = gcnew MyCSharpModule::CLRHouse();
newHouse->SetHouseNumber( pHouse->HouseNumber );
newHouse->SetHouseType( pHouse->HouseType );
...
newHouse->AddRoom ( ToCLRRoom ( pHouse->Room ) );
return newHouse;
}
C++/CLR handles marshalling of basic types such as char * to String and int to Int32 for you, so if your CLRHouse class has a member function called SetHouseNumber that takes a String, then you can call it with a char * in C++/CLR and it will do the marshalling for you.
Microsoft actually tried to make it very easy to mix CLR and Native code, and it works very well if the division between your CLR and Native code is correctly designed.