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

ikvello at common-lisp.net ikvello at common-lisp.net
Fri May 2 14:35:33 UTC 2008


Author: ikvello
Date: Fri May  2 10:35:32 2008
New Revision: 11

Modified:
   trunk/rdnzl-cpp/RDNZL/Property.cpp
Log:
Handle "AmbiguosMatch" exception produced by GetProperty in cases where a class has two properties by the same name but different return-types.

Modified: trunk/rdnzl-cpp/RDNZL/Property.cpp
==============================================================================
--- trunk/rdnzl-cpp/RDNZL/Property.cpp	(original)
+++ trunk/rdnzl-cpp/RDNZL/Property.cpp	Fri May  2 10:35:32 2008
@@ -42,6 +42,34 @@
    throw gcnew Exception (msg);
 }
 
+
+// IOK 2008-05-02: helper function for finding the most specific property with a given name.
+PropertyInfo^ GetPropertyDisambiguatingSearch(Type^ t,String^ pname, BindingFlags bindingAttr, cli::array<Type^> ^realTypes) {
+	// Primary case is just to call GetProperty. If this throws AmbiguousMatchException, this
+	// means that two properties with different return-types are present in the object (since we
+	// always pass the full set of argument types). We want the 'most specific' one, so we start
+	// searching up the inheritance tree. IOK 2008-05-02
+	try { 
+       PropertyInfo ^pi = t->GetProperty(pname, bindingAttr, nullptr, nullptr, realTypes, nullptr);
+          // The normal case, only one property with the given name found, or none.
+       return pi;
+    // Oh no, the class has several properties so named. Try to find the most specific one.
+    } catch (System::Reflection::AmbiguousMatchException ^e) {
+		e; // Shutting up the compiler since we won't be referencing this variable
+        BindingFlags declaredOnlyFlags = static_cast<BindingFlags>(bindingAttr | BindingFlags::DeclaredOnly);
+        // Starting at the given type, search upwards the inheritance hierachy for the property
+        // using the DeclaredOnly flag. 
+		for (Type^ t2 = t; nullptr != t2->BaseType; t2 = t2->BaseType) {
+          PropertyInfo ^pi = t2->GetProperty(pname , declaredOnlyFlags, nullptr, nullptr, realTypes, nullptr);
+          if (pi != nullptr) return pi;
+		}
+		// We know one will be found, but the compiler doesn't.
+		return static_cast<PropertyInfo^>(nullptr);
+	}
+}
+ 
+
+
 // helper function to get values of static and instance properties
 void *Property::getPropertyValue(Object ^o, Type  ^t, const __wchar_t *propertyName, BindingFlags bindingAttr, int nargs, void *args[]) {
   try {
@@ -56,8 +84,9 @@
       realTypes[i] = c->getContainerType();
     }
 
-    // find property by name, binding attributes and index signature
-    PropertyInfo ^pi = t->GetProperty(gcnew String(propertyName), bindingAttr, nullptr, nullptr, realTypes, nullptr);
+    // 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);
 
     if (pi == nullptr)
       throwPropertyNotFoundError(t, propertyName, realTypes, bindingAttr);
@@ -109,7 +138,7 @@
     }
 
     // find property by name, binding attributes and index signature
-    PropertyInfo ^pi = t->GetProperty(gcnew String(propertyName), bindingAttr, nullptr, nullptr, realTypes, nullptr);
+    PropertyInfo ^pi = GetPropertyDisambiguatingSearch(t,gcnew String(propertyName), bindingAttr,realTypes);
 
     if (pi == nullptr)
       throwPropertyNotFoundError(t, propertyName, realTypes, bindingAttr);



More information about the Rdnzl-cvs mailing list