[rdnzl-cvs] r10 - trunk/rdnzl-cpp/RDNZL

ikvello at common-lisp.net ikvello at common-lisp.net
Fri May 2 14:02:15 UTC 2008


Author: ikvello
Date: Fri May  2 10:02:14 2008
New Revision: 10

Modified:
   trunk/rdnzl-cpp/RDNZL/InvocationResult.cpp
Log:
CAST: Test of IsAssignale fixed, support for __ComObjects added, and better error-reporting for illegal casts. Also, test of SVN commits.

Modified: trunk/rdnzl-cpp/RDNZL/InvocationResult.cpp
==============================================================================
--- trunk/rdnzl-cpp/RDNZL/InvocationResult.cpp	(original)
+++ trunk/rdnzl-cpp/RDNZL/InvocationResult.cpp	Fri May  2 10:02:14 2008
@@ -73,17 +73,53 @@
 void *setDotNetContainerType(Type ^newType, void *ptr) {
   try {
     DotNetContainer *container = static_cast<DotNetContainer *>(ptr);
-    Type ^oldType = container->getContainerType();
-    
-    if (oldType->IsAssignableFrom(newType)) {
-      container->setContainerType(newType);
-    } else {
-      Object ^newObject = Convert::ChangeType(container->getContainerObject(), newType);
-      container->setContainerObject(newObject);
+   
+    // IOK 2008-04-25 we need the 'true' type of the object,
+    // not the 'nominal' type stored in the container, because for instance
+    // Excel will return an Array as an Object in certain situations.
+    // Type ^oldType = container->getContainerType();
+    Object ^object = container->getContainerObject();
+    Type ^oldType = object->GetType();
+   
+    // IOK 2008-04-25 The normal case - assigning to the new type is legal.
+    if (newType->IsAssignableFrom(oldType)) {
       container->setContainerType(newType);
+      return new InvocationResult();
+    }
+   
+    // When the object is actually a System.__ComObject, we can't use
+    // IsAssignable and must use QueryInterface through interop services.
+    // This happens for instance for certain objects returned from Office
+    // Interop. IOK 2008-04-25
+	if (Marshal::IsComObject(object) && newType->IsInterface) {
+		// IOK 2007-05-02 Might want to wrap this in a try{}, and 
+		//  save the exception for later just in case we could have
+		//  won using IConvert here.
+        System::IntPtr returnvalue = Marshal::GetComInterfaceForObject(object,newType);
+        bool success = (returnvalue != System::IntPtr::Zero);
+        if (success) {
+            Marshal::Release(returnvalue);
+            container->setContainerType(newType);
+            return new InvocationResult();
+        }
     }
-    // return void result
-    return new InvocationResult();
+
+    // Not directly assignable, and not a __ComObject. IConvertible objects
+	// needs to be ChangeType'd then..
+	if (nullptr != oldType->GetInterface("System.IConvertible")) {
+     Object ^newObject = Convert::ChangeType(object, newType);
+     container->setContainerObject(newObject);
+     container->setContainerType(newType);
+	 return new InvocationResult();	
+	}
+
+	// Nothing worked, so return an exception 
+	return new InvocationResult(
+				gcnew System::InvalidCastException(
+				"Invalid cast from '" + oldType->FullName + "' to '" + newType->FullName +"'"), true);
+		
+
+  // This handles exceptions thrown by Marshall::GetComInterfaceForObject and Convert::ChangeType.
   } catch (Exception ^e) {
     return new InvocationResult(e, true);
   }



More information about the Rdnzl-cvs mailing list