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

ikvello at common-lisp.net ikvello at common-lisp.net
Fri May 9 14:53:30 UTC 2008


Author: ikvello
Date: Fri May  9 10:53:29 2008
New Revision: 12

Modified:
   trunk/rdnzl-cpp/RDNZL/InvokeMember.cpp
   trunk/rdnzl-cpp/RDNZL/Property.cpp
Log:
Added support for accessing properties and methods of ComObjects with unknown interface (except for IDispatch)

Modified: trunk/rdnzl-cpp/RDNZL/InvokeMember.cpp
==============================================================================
--- trunk/rdnzl-cpp/RDNZL/InvokeMember.cpp	(original)
+++ trunk/rdnzl-cpp/RDNZL/InvokeMember.cpp	Fri May  9 10:53:29 2008
@@ -93,8 +93,21 @@
     }
 
     MethodInfo ^mi = findMethod(t, methodName, realTypes, bindingAttr);
-    if (mi == nullptr)
-      throwMethodNotFoundError(t, methodName, realTypes, bindingAttr);
+	if (mi == nullptr) {
+	  // IOK 2008-05-09 no methodinfo can mean two things: One, that there
+	  // was no method, and second, that we are dealing with a __ComObject
+	  // directly and not through an interface. These objects are sometimes
+      // returned by applications like Excel. We can then call the method
+      // using IDispatch via InvokeMember. But, the returned object will
+	  // also then typically be __ComObject, since we have no MethodInfo
+	  // object to inspect for the return-type. The user must explicitly cast to
+	  // the approprate type.
+		if (!Marshal::IsComObject(o)) throwMethodNotFoundError(t, methodName, realTypes, bindingAttr);
+		String ^name = gcnew String(methodName);
+		Object ^newInstance = t->InvokeMember(name, BindingFlags::InvokeMethod, nullptr, o, realArgs);
+		if (nullptr == newInstance) return new InvocationResult();
+		else return new InvocationResult(newInstance,newInstance->GetType());
+	}
 
     Object ^newInstance = mi->Invoke(o, realArgs);
     

Modified: trunk/rdnzl-cpp/RDNZL/Property.cpp
==============================================================================
--- trunk/rdnzl-cpp/RDNZL/Property.cpp	(original)
+++ trunk/rdnzl-cpp/RDNZL/Property.cpp	Fri May  9 10:53:29 2008
@@ -86,10 +86,21 @@
 
     // find property by name, binding attributes and index signature, handling ambiguos property references
 	// by returning the most specific.
-    PropertyInfo ^pi = GetPropertyDisambiguatingSearch(t,gcnew String(propertyName), bindingAttr,realTypes);
+	String ^propname = gcnew String(propertyName);
+    PropertyInfo ^pi = GetPropertyDisambiguatingSearch(t, propname, bindingAttr,realTypes);
 
-    if (pi == nullptr)
-      throwPropertyNotFoundError(t, propertyName, realTypes, bindingAttr);
+	if (pi == nullptr) {
+		// That the property isn't found either means it isn't there, or that our object was
+		// a __ComObject with no known interface; for which GetProperty does not work :(.
+		if (!Marshal::IsComObject(o)) throwPropertyNotFoundError(t, propertyName, realTypes, bindingAttr);
+		// Oh bother. We have a plain__ComObject, so we have to use InvokeMember, which will return
+		// another  __ComObject with no extra type information - the user must explicitly CAST this
+		// to something useful. IOK 2008-05-08
+		// Won't pass the ParameterModifier and namedParameters arguments to InvokeMember,
+		// it's not supported upstream and also not neccessary I think. IOK 2008-05-08
+		Object ^prop = t->InvokeMember(propname, BindingFlags::GetProperty, nullptr, o, realArgs);
+		return new InvocationResult(prop, prop->GetType());
+	}	
 
     return new InvocationResult(pi->GetValue(o, realArgs), pi->PropertyType);
   } catch (TargetInvocationException ^e) {
@@ -138,10 +149,23 @@
     }
 
     // find property by name, binding attributes and index signature
-    PropertyInfo ^pi = GetPropertyDisambiguatingSearch(t,gcnew String(propertyName), bindingAttr,realTypes);
+	String ^propname = gcnew String(propertyName);
+    PropertyInfo ^pi = GetPropertyDisambiguatingSearch(t,propname, bindingAttr,realTypes);
 
-    if (pi == nullptr)
-      throwPropertyNotFoundError(t, propertyName, realTypes, bindingAttr);
+	if (pi == nullptr) {	
+		// That the property isn't found either means it isn't there, or that our object was
+		// a __ComObject with no known interface; for which GetProperty does not work :(.
+		if (!Marshal::IsComObject(o)) throwPropertyNotFoundError(t, propertyName, realTypes, bindingAttr);
+		// See comments for getPropertyValue. The call below is the same, except that BindingFlags 
+		// are SetProperty, and that the args array needs to have the new values as the
+		// *last* element of the arguments.
+		Object ^newValue = static_cast<DotNetContainer *>(args[0])->getContainerObject();
+		Array::Resize(realArgs,nargs);
+		realArgs->SetValue(newValue,(nargs -1));
+
+		Object ^prop = t->InvokeMember(propname, BindingFlags::SetProperty, nullptr, o, realArgs);
+		return new InvocationResult();
+	}	
 
     // note that the new value is the first element of args
     pi->SetValue(o, static_cast<DotNetContainer *>(args[0])->getContainerObject(), realArgs);



More information about the Rdnzl-cvs mailing list