public PrePostFixesParser(IDapperMapper mapper) { Tuple <string[], bool> prefixes = mapper != null ? mapper.Prefixes : null; Tuple <string[], bool> postfixes = mapper != null ? mapper.Postfixes : null; if (prefixes != null) { this.Prefixes = prefixes.Item1; this.PrefixesExclusive = prefixes.Item2; this.PrefixesCount = prefixes.Item1.Select(x => x.Count()).Distinct(); } else { this.Prefixes = null; this.PrefixesExclusive = false; this.PrefixesCount = new int[] { 0 }; } if (postfixes != null) { this.Postfixes = postfixes.Item1; this.PostfixesExclusive = postfixes.Item2; this.PostfixesCount = postfixes.Item1.Select(x => x.Count()).Distinct(); } }
/// <summary> /// Store a mapper object in static dictionary. /// </summary> /// <param name="t"></param> /// <param name="mapper"></param> public void StoreMapper(Type t, IDapperMapper mapper) { if (!_Mappers.ContainsKey(t)) { _Mappers.Add(t, mapper); } }
protected dynamic GetCleanResult(IEnumerable <dynamic> result, IDapperMapper mapper, bool clean) { PrePostFixesParser parser = new PrePostFixesParser(mapper); if (!clean) { return(result.Select(dyn => parser.GetTypeMembersWithoutPrePostFixes(dyn, mapper.NamesList))); } else { return(result.Select(dyn => parser.RemovePrePostFixesFromDictionary(dyn))); } }
/// <summary> /// Get mapper of type t. If type t haven't been stored by StoreType, returns null. If type t have been stored and there are no mapper /// created yet, it creates a new one, store it, and return it. /// </summary> /// <param name="t"></param> /// <returns></returns> public IDapperMapper GetMapper(Type t) { if (_Mappers.ContainsKey(t)) { return(_Mappers[t]); } if (!_TypesToMap.Contains(t)) { return(null); } IDapperMapper mapper = (IDapperMapper)Activator.CreateInstance(typeof(DapperMapper <>).MakeGenericType(t), this); StoreMapper(t, mapper); return(mapper); }
protected dynamic GetCleanResult(dynamic dyn, IDapperMapper keysMapper, string valuesName, bool clean) { var KeysParser = new PrePostFixesParser(keysMapper); var typeMembers = new ExpandoObject() as IDictionary <string, object>; if (!clean) { typeMembers = KeysParser.GetTypeMembersWithoutPrePostFixes(dyn, keysMapper.NamesList); typeMembers.Add(valuesName, ((IDictionary <string, object>)dyn)[valuesName]); } else { typeMembers = KeysParser.RemovePrePostFixesFromDictionary(dyn); typeMembers.Add(valuesName, ((IDictionary <string, object>)dyn)[valuesName]); } return(typeMembers); }
/// <summary> /// Returns true if a mapper exists or can be created, and set it as iDapperMapper. /// If type t haven't been stored by StoreType, returns false. If type t have been stored and there are no mapper /// created yet, it creates a new one, store it, set it as iDapperMapper and returns true. /// </summary> /// <param name="t"></param> /// <param name="mapper"></param> /// <returns></returns> public bool GetMapper(Type t, out IDapperMapper mapper) { if (_Mappers.ContainsKey(t)) { mapper = _Mappers[t]; return(true); } if (!_TypesToMap.Contains(t)) { mapper = null; return(false); } mapper = (IDapperMapper)Activator.CreateInstance(typeof(DapperMapper <>).MakeGenericType(t), this); StoreMapper(t, mapper); return(false); }
protected dynamic GetCleanResult(dynamic dyn, IDapperMapper keysMapper, IDapperMapper valuesMapper, bool clean) { var KeysParser = new PrePostFixesParser(keysMapper); var ValuesParser = new PrePostFixesParser(valuesMapper); var typeMembers = new ExpandoObject() as IDictionary <string, object>; if (!clean) { typeMembers = KeysParser.GetTypeMembersWithoutPrePostFixes(dyn, keysMapper.NamesList); typeMembers = typeMembers .Concat((IDictionary <string, object>)ValuesParser.GetTypeMembersWithoutPrePostFixes(dyn, valuesMapper.NamesList)) .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); } else { typeMembers = KeysParser.RemovePrePostFixesFromDictionary(dyn); typeMembers = typeMembers .Concat((IDictionary <string, object>)ValuesParser.RemovePrePostFixesFromDictionary(dyn)) .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); } return(typeMembers); }
public DictionaryMapper( IEnumerable <dynamic> dResult, string memberName, bool nested, bool isAnInterface, bool cleanResult, Type memberType, IDapperMapper masterMapper) { Type masterType = masterMapper.TType; if (!cleanResult && !nested) { IEnumerable <dynamic> clean; var parser = new PrePostFixesParser(masterMapper); clean = dResult.Select(dyn => parser.GetTypeMembersWithoutPrePostFixes(dyn, masterMapper.NamesList)); GetDummyDictionary(dResult, memberName, false, isAnInterface, /*allowDuplicates, */ true, memberType, masterType); } else { GetDummyDictionary(dResult, memberName, nested, isAnInterface, /*allowDuplicates, */ cleanResult, memberType, masterType); } }
/// <summary> /// コンストラクタ /// </summary> /// <param name="connection"></param> public ContextFixedTime(DapperMapper connection) { _Connection = connection ?? throw new ArgumentNullException(nameof(connection)); }
/// <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); }
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) }); } } } } }
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]})"); } } }