[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