private void GetDummyDictionary( IEnumerable <dynamic> dResult, string memberName, bool nested, bool isAnInterface, bool cleanResult, Type dictType, Type masterType) { string[] keyValueNames = _Dictionaries[masterType][memberName]; Type keysType = dictType.GenericTypeArguments[0]; //keys types of dummy dict Type valuesType = dictType.GenericTypeArguments[1]; //values types of dummy dict this.DummyDictionary = (IDictionary)Activator.CreateInstance(typeof(Dictionary <,>).MakeGenericType(dictType.GenericTypeArguments)); if (!nested) { bool noKeys = true; foreach (dynamic dyn in dResult) { IDictionary <string, object> dict = dyn as IDictionary <string, object>; if (!dict.ContainsKey(keyValueNames[0])) { continue; } if (this.DummyDictionary.Contains(dict[keyValueNames[0]])) { continue; } noKeys = false; if (!dict.ContainsKey(keyValueNames[1])) { DummyDictionary.Add(dict[keyValueNames[0]], GetDefault(valuesType)); } else { DummyDictionary.Add(dict[keyValueNames[0]], dict[keyValueNames[1]]); } } //if there aren't any key correct, exception if (noKeys)//preDummy == null)//(!preDummy.Any(dyn => dyn.ContainsKey(keyValueNames[0]))) { throw new CustomException_DapperMapper( $@"DictionaryMapper.GetDummyDictionary: Dynamic dapper result doesn't have members with the name required to create dictionary {memberName} keys in {masterType.Name}. Key-value names configurated: ({keyValueNames[0]}, {keyValueNames[1]})"); } } else { MapperStore store = new MapperStore(); if (isAnInterface) { bool keysAreInterface = keysType.IsInterface && !typeof(IDictionary).IsAssignableFrom(keysType) && !(typeof(IEnumerable).IsAssignableFrom(keysType) && !typeof(string).IsAssignableFrom(keysType)); bool valuesAreInterface = valuesType.IsInterface && !typeof(IDictionary).IsAssignableFrom(valuesType) && !(typeof(IEnumerable).IsAssignableFrom(valuesType) && !typeof(string).IsAssignableFrom(valuesType)); if (keysAreInterface) { keysType = ResolveInterface(keysType, dResult); } if (valuesAreInterface) { valuesType = ResolveInterface(valuesType, dResult); } } iDapperMapper keysNestedMapper = store.GetMapper(keysType); iDapperMapper valuesNestedMapper = store.GetMapper(valuesType); //if there aren't any key correct, exception if (keysNestedMapper != null && !keysNestedMapper.CheckIfDynamicHasAllTypeMembersByName(dResult.First())) { throw new CustomException_DapperMapper( $@"DictionaryMapper.GetDummyDictionary: Dynamic dapper result doesn't have members with the name required to create dictionary {memberName} in {masterType.Name}. Key-value names configurated: ({keyValueNames[0]}, {keyValueNames[1]})"); } //if both keys and values are nested types if (keysNestedMapper != null && valuesNestedMapper != null) { foreach (dynamic dyn in dResult) { dynamic cleanDyn = GetCleanResult(dyn, keysNestedMapper, valuesNestedMapper, cleanResult); object key = keysNestedMapper.NoGenericMap(cleanDyn, true); if (this.DummyDictionary.Contains(key)) { continue; } this.DummyDictionary.Add( key, valuesNestedMapper.NoGenericMap(cleanDyn, true)); } } //if only values are nested else if (keysNestedMapper == null) { foreach (dynamic dyn in dResult) { IDictionary <string, object> dict = (IDictionary <string, object>)dyn; if (!dict.ContainsKey(keyValueNames[0])) { continue; } dynamic cleanDyn = GetCleanResult(dyn, keyValueNames[0], valuesNestedMapper, cleanResult); dict = (IDictionary <string, object>)cleanDyn; if (this.DummyDictionary.Contains(dict[keyValueNames[0]])) { continue; } if (!dict.ContainsKey(keyValueNames[1])) { this.DummyDictionary.Add(dict[keyValueNames[0]], GetDefault(valuesType)); } else { this.DummyDictionary.Add(dict[keyValueNames[0]], valuesNestedMapper.NoGenericMap(cleanDyn, true)); } } } //if only keys are nested else { //bool noKeys = true; foreach (dynamic dyn in dResult) { IDictionary <string, object> dict = (IDictionary <string, object>)dyn; //if (!keysNestedMapper.CheckIfDynamicHasAllTypeMembersByName(dyn)) continue; //noKeys = false; dynamic cleanDyn = GetCleanResult(dyn, keysNestedMapper, keyValueNames[1], cleanResult); dict = (IDictionary <string, object>)cleanDyn; object key = keysNestedMapper.NoGenericMap(cleanDyn, true); if (this.DummyDictionary.Contains(key)) { continue; } if (!dict.ContainsKey(keyValueNames[1])) { this.DummyDictionary.Add(key, GetDefault(valuesType)); } else { this.DummyDictionary.Add(key, dict[keyValueNames[1]]); } } //if there aren't any key correct, exception // if (noKeys)//preDummy == null) // throw new CustomException_DapperMapper( // $@"DictionaryMapper.GetDummyDictionary: Dynamic dapper result doesn't have members with the name //required to create dictionary {memberName} in {masterType.Name}. Key-value names configurated: ({keyValueNames[0]}, {keyValueNames[1]})"); } } }
private void GetDummyEnumerable(IEnumerable <dynamic> cleanDapperResult, string memberName, bool nested, bool allowDuplicates, Type enumType, Type TType) { if (!nested) { if (!allowDuplicates) { this.DummyEnumerable = cleanDapperResult .Select(dyn => (IDictionary <string, object>)dyn) .Select(dict => dict[memberName]) .Distinct(); } else { this.DummyEnumerable = cleanDapperResult .Select(dyn => (IDictionary <string, object>)dyn) .Select(dict => dict[memberName]); } } else { Type genericType = enumType.GenericTypeArguments[0]; bool genericIsInterface = genericType.IsInterface && !typeof(IDictionary).IsAssignableFrom(genericType) && !(typeof(IEnumerable).IsAssignableFrom(genericType) && !typeof(string).IsAssignableFrom(genericType)); if (genericIsInterface) { genericType = ResolveInterface(genericType, cleanDapperResult); } MapperStore store = new MapperStore(); iDapperMapper nestedMapper = store.GetMapper(genericType); if (typeof(IList).IsAssignableFrom(enumType)) { IList result = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(genericType)); if (!allowDuplicates) { IEnumerable <dynamic> distinctCleanResult = nestedMapper.GetDistinctDapperResult(cleanDapperResult, true); foreach (dynamic dyn in distinctCleanResult) { result.Add(nestedMapper.NoGenericMap(dyn, true)); } } else { foreach (dynamic dyn in cleanDapperResult) { result.Add(nestedMapper.NoGenericMap(dyn, true)); } } this.DummyEnumerable = result; } else { //http://stackoverflow.com/questions/18251587/assign-any-ienumerable-to-object-property var addMethod = enumType.GetMethod("Add", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); // Property doesn't support Adding if (addMethod == null) //throw new InvalidOperationException("Method Add does not exist on class " + enumType.Name); { throw new CustomException_DapperMapper( $@"EnumerableMapper.GetDummyEnumerable: Method Add doesn't exist in enumerable type to map. enumType: {enumType.Name} ; member name: {memberName}."); } if (enumType.IsGenericTypeDefinition) { this.DummyEnumerable = (IEnumerable)Activator.CreateInstance(enumType.MakeGenericType(genericType)); } else { this.DummyEnumerable = (IEnumerable)Activator.CreateInstance(enumType); } if (!allowDuplicates) { IEnumerable <dynamic> distinctCleanResult = nestedMapper.GetDistinctDapperResult(cleanDapperResult, true); foreach (dynamic dyn in distinctCleanResult) { addMethod.Invoke(this.DummyEnumerable, new object[] { nestedMapper.NoGenericMap(dyn, true) }); } } else { foreach (dynamic dyn in cleanDapperResult) { addMethod.Invoke(this.DummyEnumerable, new object[] { nestedMapper.NoGenericMap(dyn, true) }); } } } } }
/// <summary> /// Generic Map. /// </summary> /// <param name="dapperResult"></param> /// <returns></returns> public T Map(IEnumerable <dynamic> dapperResult, bool cleanResult = false) { var parser = new PrePostFixesParser(this); T mapped = this.NewObject(dapperResult.First()); if (_OnlyConstructor.Contains(this.TType)) { return(mapped); } //TODO: divide el siguiente foreach en dos con dos nuevos diccionarios estáticos, uno para pInfos y otro para fInfos, //aunque se repita código: hacer métodos para cada parte del código del tipo: //private T PreMapCreator(KeyValuePair<PropertyInfo, MemberTypeInfo> kvp, IEnumerable<dynamic> dapperResult, bool cleanResult = false) //private T PreMapIEnumerable(KeyValuePair<PropertyInfo, MemberTypeInfo> kvp, IEnumerable<dynamic> dapperResult, bool cleanResult = false) //... //Loop through all members foreach (KeyValuePair <MemberInfo, MemberTypeInfo> kvp in mtInfos) { if (kvp.Value == MemberTypeInfo.Ignore) { continue; } //Member have a creator else if ((kvp.Value & MemberTypeInfo.Creator) == MemberTypeInfo.Creator) { //MemberDelegate mDel = (MemberDelegate)_MembersCreators[this.TType][kvp.Key.Name]; Func <dynamic, object> mDel = (Func <dynamic, object>)_MembersCreators[this.TType][kvp.Key.Name]; if (kvp.Key.MemberType == MemberTypes.Property) { ((PropertyInfo)kvp.Key).SetValue(mapped, mDel(dapperResult)); } else { ((FieldInfo)kvp.Key).SetValue(mapped, mDel(dapperResult)); } } //Member is IDictionary or IEnumerable else if ((kvp.Value & MemberTypeInfo.IEnumerable) == MemberTypeInfo.IEnumerable) { Type t = GetMemberType(kvp.Key); //if ((kvp.Value & MemberTypeInfo.Interface) == MemberTypeInfo.Interface) t = ResolveInterface(kvp.Key, dapperResult); //else t = GetMemberType(kvp.Key); /* * { * //Type of property or field * if (kvp.Key.MemberType == MemberTypes.Property) t = ((PropertyInfo)kvp.Key).PropertyType; * else t = ((FieldInfo)kvp.Key).FieldType; * }*/ bool isAnInterface = (kvp.Value & MemberTypeInfo.Interface) == MemberTypeInfo.Interface; bool isNested = (kvp.Value & MemberTypeInfo.Nested) == MemberTypeInfo.Nested; //If member is a dictionary if (typeof(IDictionary).IsAssignableFrom(t)) { //Create a dummy dictionary with the dapper's dynamic result which should be equal to the final one DictionaryMapper dictMapper = new DictionaryMapper(dapperResult, kvp.Key.Name, isNested, isAnInterface, cleanResult, t, this); try { if (kvp.Key.MemberType == MemberTypes.Property) { ((PropertyInfo)kvp.Key).SetValue(mapped, dictMapper.DummyDictionary); } else { ((FieldInfo)kvp.Key).SetValue(mapped, dictMapper.DummyDictionary); } } catch (Exception err) { throw new CustomException_DapperMapper( $@"DapperMapper.Map: Couldn't map IDictionary member {kvp.Key.Name} with value contained by dynamic object. Incorrect type of value?: {kvp.Value.ToString()}", err); } } //Rest of enumerables else { IEnumerable <dynamic> iEnumDapperResult; //Select current member's values from dynamic if (isNested && !cleanResult) { //Type mType = t; // GetMemberType(kvp.Key);//IEnumerable<T> Type genericType = t.GenericTypeArguments[0];//mType.GenericTypeArguments[0];//T if ((kvp.Value & MemberTypeInfo.Interface) == MemberTypeInfo.Interface) { bool genericIsInterfaceNotIEnumerable = genericType.IsInterface && !typeof(IDictionary).IsAssignableFrom(genericType) && !(typeof(IEnumerable).IsAssignableFrom(genericType) && !typeof(string).IsAssignableFrom(genericType)); if (genericIsInterfaceNotIEnumerable) { genericType = ResolveInterface(genericType, dapperResult); } } iDapperMapper nestedMapper = MappersStore.GetMapper(genericType); var nestedParser = new PrePostFixesParser(nestedMapper); iEnumDapperResult = dapperResult .Select(dyn => nestedParser.GetTypeMembersWithoutPrePostFixes(dyn, nestedMapper.NamesList)); } else if (!cleanResult) { iEnumDapperResult = dapperResult.Select(dyn => parser.RemovePrePostFixesFromDictionary(dyn)); } else { iEnumDapperResult = dapperResult; } //Create dummy IEnumerable EnumerableMapper enumMapper = new EnumerableMapper(iEnumDapperResult, kvp.Key.Name, isNested, t, this.TType);; var dummy = Activator.CreateInstance(t, enumMapper.DummyEnumerable); try { if (kvp.Key.MemberType == MemberTypes.Property) { ((PropertyInfo)kvp.Key).SetValue(mapped, dummy); } else { ((FieldInfo)kvp.Key).SetValue(mapped, dummy); } } catch (Exception err) { throw new CustomException_DapperMapper( $@"DapperMapper.Map: Couldn't map IEnumerable member {kvp.Key.Name} with value contained by dynamic object. Incorrect type of value?: {kvp.Value.ToString()}", err); } } }//End IDictionary/IEnumerable //If Built-in else if ((kvp.Value & MemberTypeInfo.BuiltIn) == MemberTypeInfo.BuiltIn) { string name = parser.RemoveFieldsUnderscore(kvp.Key.Name); IDictionary <string, object> dapperDict; if (!cleanResult) { dapperDict = parser.GetTypeMembersWithoutPrePostFixes(dapperResult.First(), NamesList) as IDictionary <string, object>; } else { dapperDict = dapperResult.First() as IDictionary <string, object>; } if (!dapperDict.ContainsKey(name)) { throw new CustomException_DapperMapper( $@"DapperMapper.Map: There's no member in dynamic dapper result with name {kvp.Key.Name}. Cannot Map object."); } try { if (kvp.Key.MemberType == MemberTypes.Property) { ((PropertyInfo)kvp.Key).SetValue(mapped, dapperDict[name]); } else { ((FieldInfo)kvp.Key).SetValue(mapped, dapperDict[name]); } } catch (Exception err) { throw new CustomException_DapperMapper( $@"DapperMapper.Map: Couldn't map BuiltIn-type member {kvp.Key.Name} with value contained by dynamic object. Incorrect type of value?: {kvp.Value.ToString()}", err); } } //if nested else if ((kvp.Value & MemberTypeInfo.Nested) == MemberTypeInfo.Nested) { Type mType = GetMemberType(kvp.Key); if ((kvp.Value & MemberTypeInfo.Interface) == MemberTypeInfo.Interface) { mType = ResolveInterface(mType, dapperResult); } //access generic Map method through nongeneric interface method iDapperMapper nestedMapper = MappersStore.GetMapper(mType); if (nestedMapper == null) { throw new CustomException_DapperMapper( $@"DapperMapper.Map: No Mapper found at store for property {kvp.Key.Name} of type {mType.ToString()}. If you want to map a nested property you have to create a mapper for that property type."); } if (kvp.Key.MemberType == MemberTypes.Property) { ((PropertyInfo)kvp.Key).SetValue(mapped, nestedMapper.NoGenericMap(dapperResult, cleanResult)); } else { ((FieldInfo)kvp.Key).SetValue(mapped, nestedMapper.NoGenericMap(dapperResult, cleanResult)); } } } return(mapped); }