public static object ToModel(Document document, Type modelType)
{
var model = Activator.CreateInstance(modelType);
foreach (var prop in modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (TypeHelper.IsSimpleType(prop.PropertyType))
{
var field = document.GetField(prop.Name);
if (field != null)
{
var propValue = LuceneUtility.FromFieldStringValue(field.StringValue, prop.PropertyType);
prop.SetValue(model, propValue, null);
}
}
else
{
var propTypeInfo = ModelTypeInfo.GetTypeInfo(prop.PropertyType);
if (propTypeInfo.IsCollection)
{
if (propTypeInfo.IsDictionary)
{
var propValue = prop.GetValue(model, null);
if (propValue == null)
{
propValue = Activator.CreateInstance(typeof(Dictionary<,>).MakeGenericType(propTypeInfo.DictionaryKeyType, propTypeInfo.DictionaryValueType));
prop.SetValue(model, propValue, null);
}
var dic = propValue as IDictionary;
var fields = document.GetFields().Where(f => f.Name.StartsWith(prop.Name));
// Property type is IDictionary<TKey, TValue>
if (TypeHelper.IsSimpleType(propTypeInfo.DictionaryValueType))
{
foreach (var field in fields)
{
string propName;
string dicKey;
if (TryParseDictionaryFieldName(field.Name, out propName, out dicKey))
{
var fieldValue = LuceneUtility.FromFieldStringValue(field.StringValue, propTypeInfo.DictionaryValueType);
dic.Add(dicKey, fieldValue);
}
}
}
else // Property type is IDictionary<TKey, IList<TValue>> or IDictionary<TKey, ISet<TValue>>
{
var dicValueTypeInfo = ModelTypeInfo.GetTypeInfo(propTypeInfo.DictionaryValueType);
if (dicValueTypeInfo.IsCollection && TypeHelper.IsSimpleType(dicValueTypeInfo.ElementType))
{
Type newDicValueType = null;
MethodInfo hashsetAddMethod = null;
if (dicValueTypeInfo.IsSet)
{
newDicValueType = typeof(HashSet<>).MakeGenericType(dicValueTypeInfo.ElementType);
hashsetAddMethod = GetAddMethod(newDicValueType, dicValueTypeInfo.ElementType);
}
else
{
newDicValueType = typeof(List<>).MakeGenericType(dicValueTypeInfo.ElementType);
}
foreach (var field in fields)
{
string propName;
string dicKey;
if (TryParseDictionaryFieldName(field.Name, out propName, out dicKey))
{
var fieldValue = LuceneUtility.FromFieldStringValue(field.StringValue, dicValueTypeInfo.ElementType);
if (!dic.Contains(dicKey))
{
dic.Add(dicKey, Activator.CreateInstance(newDicValueType));
}
var list = dic[dicKey];
if (dicValueTypeInfo.IsSet) // is HashSet<>
{
hashsetAddMethod.Invoke(list, new[] { fieldValue });
}
else // is IList<>
{
(list as IList).Add(fieldValue);
}
}
}
}
}
}
else // Property is collection but not dictionary
{
var fields = document.GetFields(prop.Name);
if (fields.Length == 0)
{
continue;
}
var list = Activator.CreateInstance(typeof(List<>).MakeGenericType(propTypeInfo.ElementType)) as IList;
foreach (var field in fields)
{
var fieldValue = LuceneUtility.FromFieldStringValue(field.StringValue, propTypeInfo.ElementType);
list.Add(fieldValue);
}
if (prop.PropertyType.IsArray)
{
prop.SetValue(model, list.OfType<object>().ToArray(), null);
}
else
{
prop.SetValue(model, list, null);
}
}
}
}
}
return model;
}