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);