public static object ParseFieldValue(Type modelType, string field, string fieldValue) { if (String.IsNullOrWhiteSpace(fieldValue) || fieldValue == "*" || fieldValue == "NULL") { return(null); } var prop = modelType.GetProperty(field, BindingFlags.Public | BindingFlags.Instance); if (prop == null) { // if not corresponding property was found, it might be custom fields, they are all treated as string return(fieldValue); } if (TypeHelper.IsSimpleType(prop.PropertyType)) { return(LuceneUtility.FromFieldStringValue(fieldValue, prop.PropertyType)); } var propTypeInfo = ModelTypeInfo.GetTypeInfo(prop.PropertyType); if (propTypeInfo.IsDictionary) { return(LuceneUtility.FromFieldStringValue(fieldValue, propTypeInfo.DictionaryValueType)); } else if (propTypeInfo.IsCollection) { return(LuceneUtility.FromFieldStringValue(fieldValue, propTypeInfo.ElementType)); } return(null); }
static IEnumerable <IFieldable> ToFields(object container, PropertyInfo property) { var fieldAttr = property.GetCustomAttribute <FieldAttribute>(false) ?? new FieldAttribute(Field.Index.NOT_ANALYZED, Field.Store.YES); var propType = ModelTypeInfo.GetTypeInfo(property.PropertyType); if (propType.IsSimpleType) { var propValue = property.GetValue(container, null); yield return(fieldAttr.CreateLuceneField(property.Name, propValue)); } else { if (propType.IsCollection) { if (propType.IsDictionary) { if (!TypeHelper.IsSimpleType(propType.DictionaryKeyType)) { throw new NotSupportedException("Not support complex dictionary key."); } if (TypeHelper.IsSimpleType(propType.DictionaryValueType)) { var dic = property.GetValue(container, null) as IDictionary; foreach (DictionaryEntry entry in dic) { var fieldName = GetDictionaryFieldName(property.Name, entry.Key.ToString()); yield return(fieldAttr.CreateLuceneField(fieldName, entry.Value)); } } else { var valueTypeInfo = ModelTypeInfo.GetTypeInfo(propType.DictionaryValueType); if (valueTypeInfo.IsCollection && !valueTypeInfo.IsDictionary && TypeHelper.IsSimpleType(valueTypeInfo.ElementType)) { var dic = property.GetValue(container, null) as IDictionary; foreach (DictionaryEntry entry in dic) { var fieldName = GetDictionaryFieldName(property.Name, entry.Key.ToString()); var values = entry.Value as IEnumerable; foreach (var value in values) { yield return(fieldAttr.CreateLuceneField(fieldName, value)); } } } else { throw new NotSupportedException("Not support dictionary property with value type other than simple type and simple type collection."); } } } else { if (!TypeHelper.IsSimpleType(propType.ElementType)) { throw new NotSupportedException("Not support complex collection element."); } var items = property.GetValue(container, null) as IEnumerable; if (items != null) { foreach (var item in items) { yield return(fieldAttr.CreateLuceneField(property.Name, item)); } } } } } }
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); }
protected virtual void MapComplexProperty(PropertyInfo targetProperty, PropertyInfo sourceProperty, object sourcePropValue, object source, object target, Type sourceType, Type targetType, string propertyPath, MappingContext context) { object targetPropValue = targetProperty.GetValue(target, null); if (context.VisitedObjects.Contains(targetPropValue)) { return; } var targetPropTypeInfo = ModelTypeInfo.GetTypeInfo(targetProperty.PropertyType); if (targetPropTypeInfo.IsCollection) { var sourcePropTypeInfo = ModelTypeInfo.GetTypeInfo(sourceProperty.PropertyType); if (targetPropTypeInfo.IsDictionary) { if (sourcePropTypeInfo.IsDictionary) { // Map between dictionaries var targetDic = Activator.CreateInstance(typeof(Dictionary <,>).MakeGenericType(targetPropTypeInfo.DictionaryKeyType, targetPropTypeInfo.DictionaryValueType)) as IDictionary; targetProperty.SetValue(target, targetDic, null); var sourceDic = sourcePropValue as IDictionary; foreach (var key in sourceDic.Keys) { targetDic.Add(key, sourceDic[key]); } } else if (sourcePropTypeInfo.IsCollection) { // source collection element: Name or Key field -> dictionary key, Value field -> dictionary value var keyProp = sourcePropTypeInfo.ElementType.GetProperty("Key", BindingFlags.Public | BindingFlags.Instance); if (keyProp == null) { keyProp = sourcePropTypeInfo.ElementType.GetProperty("Name", BindingFlags.Public | BindingFlags.Instance); } if (keyProp != null) { var valueProp = sourcePropTypeInfo.ElementType.GetProperty("Value", BindingFlags.Public | BindingFlags.Instance); if (valueProp != null) { var targetDic = Activator.CreateInstance(typeof(Dictionary <,>).MakeGenericType(targetPropTypeInfo.DictionaryKeyType, targetPropTypeInfo.DictionaryValueType)) as IDictionary; foreach (var item in sourcePropValue as IEnumerable) { var key = keyProp.GetValue(item, null); var value = valueProp.GetValue(item, null); targetDic.Add(key, value); } targetProperty.SetValue(target, targetDic, null); } } } } else // List or Array { var sourceElementType = sourcePropTypeInfo.ElementType; var elementMapper = GetMapperOrDefault(sourceElementType, targetPropTypeInfo.ElementType); if (elementMapper == null) { return; } var targetList = Activator.CreateInstance(typeof(List <>).MakeGenericType(targetPropTypeInfo.ElementType)); var addMethod = targetList.GetType().GetMethod("Add", BindingFlags.Public | BindingFlags.Instance, null, new[] { targetPropTypeInfo.ElementType }, null); var sourceList = sourcePropValue as IEnumerable; var elementPrefix = propertyPath + "."; var totalElements = 0; foreach (var sourceElement in sourceList) { var targetElement = elementMapper.Map(sourceElement, Activator.CreateInstance(targetPropTypeInfo.ElementType), sourceElementType, targetPropTypeInfo.ElementType, elementPrefix, context); addMethod.Invoke(targetList, new[] { targetElement }); totalElements++; } if (!Object.ReferenceEquals(targetList, targetPropValue)) { if (targetProperty.PropertyType.IsArray) { var array = Array.CreateInstance(targetPropTypeInfo.ElementType, totalElements); var i = 0; foreach (var item in targetList as IEnumerable) { array.SetValue(item, i); i++; } targetProperty.SetValue(target, array, null); } else { targetProperty.SetValue(target, targetList, null); } } } } else { var mapper = GetMapperOrDefault(sourceProperty.PropertyType, targetProperty.PropertyType); if (mapper != null) { if (targetPropValue == null) { targetPropValue = Activator.CreateInstance(targetProperty.PropertyType); } targetPropValue = mapper.Map(sourcePropValue, targetPropValue, sourceProperty.PropertyType, targetProperty.PropertyType, propertyPath + ".", context); targetProperty.SetValue(target, targetPropValue, null); } } }