[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