I have results (xml format, <Prop0>
, <Prop1>
, ...) coming from an API that I am saving into my database table. I have a mapping of the Props to my table columns. I would like to create an object on the fly with property names coming from the mapping and values coming from the API results.
I could use the mapping dictionary and the API results to directly save the values in the database, but all the insert functions (remote to my application) are designed to use List of objects.
I have explored System.Dynamic.ExpandoObject but one cannot add properties on the fly to it (from, say, a dictionary). Currently, I am using the following generic but strongly typed solution, for which all the attributes need to be present in the class.
internal T FetchPopulatedObject<T>(Dictionary<string, string> apiToTableMapping, Dictionary<string, string> apiResultsKeyVal, T objectToPopulate) where T : new()
{
if (objectToPopulate == null)
objectToPopulate = new T();
PropertyInfo currProp;
Type currActualType;
string valToSet = string.Empty;
int valToSetNumeric = 0;
object finalValToSet = new object();
foreach (KeyValuePair<string, string> currMap in apiToTableMapping)
{
valToSet = string.Empty;
currProp = (typeof(T).GetProperty(currMap.Value));
if (currProp == null)
{
log.Info("Could not find property for table column " + currMap.Value + ". Moving on.");
continue;
}
bool valResult = apiResultsKeyVal.TryGetValue(currMap.Key, out valToSet);
if (!valResult)
{
log.Info("Could not find value in API Results for property: " + currMap.Key + ".");
continue;
}
currActualType = Nullable.GetUnderlyingType(currProp.PropertyType) ?? currProp.PropertyType;
if (string.IsNullOrEmpty(valToSet))
{
log.Info("Property " + currProp.Name + " is of " + currProp.PropertyType.Name + " type but API attribute " +
currMap.Key + " returned an incompatible or empty value " + valToSet + ". Skipping this field.");
continue;
}
else
{
finalValToSet = Int32.TryParse(valToSet, out valToSetNumeric) ? Convert.ChangeType(valToSetNumeric, currActualType) : Convert.ChangeType(valToSet, currActualType);
}
currProp.SetValue(objectToPopulate, finalValToSet, null);
}
return objectToPopulate;
}
However, this is infeasible, since the API results keep changing and adding new attributes.
Can somebody suggest how to accomplish the same without having to have all the properties already in class T?