in src/main/csharp/Util/IntrospectionSupport.cs [164:282]
public static void SetProperties(object target,
StringDictionary valueMap,
StringDictionary nameMap)
{
Tracer.DebugFormat("SetProperties called with target: {0}",
target.GetType().Name);
// Application of specified values is recursive. If a key does not
// correspond to a member of the current target object, it is
// supposed to refer to a sub-member of such a member. Since member
// keys can contain dot characters, an attempt is made to find the
// "longest" key corresponding to a member of the current object
// (this identifies the "sub-target"), and extract the remaining
// key characters as a sub-key to sub-members.
// The following dictionary indexes keys to "sub-targets", and
// "sub-key"/value pairs to assign to "sub-targets".
Dictionary<string, StringDictionary> subTargetMap = null;
foreach(string key in valueMap.Keys)
{
if(nameMap.ContainsKey(key))
{
// Key refers to a member of the current target
string memberName = nameMap[key];
MemberInfo member = FindMemberInfo(target, memberName);
if(member == null)
{
// Should not happen if the nameMap was indeed created
// for the current target object...
throw new NMSException(string.Format(
"No such property or field: {0} on class: {1}",
memberName, target.GetType().Name));
}
// Set value
try
{
if(member.MemberType == MemberTypes.Property)
{
PropertyInfo property = (PropertyInfo)member;
object value = ConvertValue(valueMap[key],
property.PropertyType);
property.SetValue(target, value, null);
}
else
{
FieldInfo field = (FieldInfo)member;
object value = ConvertValue(valueMap[key],
field.FieldType);
field.SetValue(target, value);
}
}
catch(Exception ex)
{
throw NMSExceptionSupport.Create(
"Error while attempting to apply option.", ex);
}
}
else
{
// Key does NOT refers to a member of the current target
// Extract maximal member key + subkeys
string memberKey = key;
int dotPos = memberKey.LastIndexOf('.');
bool memberFound = false;
while(!memberFound && dotPos > 0)
{
memberKey = memberKey.Substring(0, dotPos);
if(nameMap.ContainsKey(memberKey))
{
memberKey = nameMap[memberKey];
memberFound = true;
}
else
{
dotPos = memberKey.LastIndexOf('.');
}
}
if(!memberFound)
{
throw new NMSException(string.Format(
"Unknown property or field: {0} on class: {1}",
key, target.GetType().Name));
}
// Register memberKey, subKey and value for further processing
string subKey = key.Substring(dotPos + 1);
StringDictionary subValueMap;
if(subTargetMap == null)
{
subTargetMap = new Dictionary<string, StringDictionary>();
}
if(!subTargetMap.TryGetValue(memberKey, out subValueMap))
{
subValueMap = new StringDictionary();
subTargetMap.Add(memberKey, subValueMap);
}
// In theory, we can't have the same subkey twice, since
// they were unique subkeys from another dictionary.
// Therefore, no need to check for subValueMap.ContainsKey.
subValueMap.Add(subKey, valueMap[key]);
}
}
// Now process any compound assignments.
if(subTargetMap != null)
{
foreach(string subTargetKey in subTargetMap.Keys)
{
MemberInfo member = FindMemberInfo(target, subTargetKey);
object subTarget = GetUnderlyingObject(member, target);
SetProperties(subTarget, subTargetMap[subTargetKey]);
}
}
}