internal static Func <DbDataReader, object> GetReader(int hashKey, Type targetType, DbDataReader reader, bool isIgnoreCase) { int readerKey = GetReaderKey(targetType, hashKey); if (!ReaderCache.ContainsKey(readerKey)) { string propName = null; PropertyInfo propInfo = null; var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; if (isIgnoreCase) { bindingFlags |= BindingFlags.IgnoreCase; } List <string> propNameList = new List <string>(); for (int i = 0; i < reader.FieldCount; i++) { propName = reader.GetName(i); propInfo = targetType.GetProperty(propName, bindingFlags); if (propInfo == null) { continue; } propNameList.Add(propInfo.Name); } var readerHandler = DbTypeMap.ContainsKey(targetType) ? CreateValueReaderHandler(targetType, reader.GetOrdinal(propName)) : CreateTypeReaderHandler(targetType, propNameList, reader); ReaderCache.TryAdd(readerKey, readerHandler); } return(ReaderCache[readerKey]); }
private static void CreateParamter(ILGenerator il, string paramPrefix, KeyValuePair <string, object> colMapper) { il.Emit(OpCodes.Dup); il.Emit(OpCodes.Ldarg_0); il.EmitCall(OpCodes.Callvirt, typeof(IDbCommand).GetMethod(nameof(IDbCommand.CreateParameter), Type.EmptyTypes), null); // stack is now [parameters][parameters][parameter] il.Emit(OpCodes.Dup); il.Emit(OpCodes.Ldstr, paramPrefix + colMapper.Key); il.EmitCall(OpCodes.Callvirt, typeof(IDataParameter).GetProperty(nameof(IDataParameter.ParameterName)).GetSetMethod(), null); // stack is now [parameters][parameters][parameter] var memberType = colMapper.Value.GetType(); var dbType = DbTypeMap.LookupDbType(colMapper.Value.GetType()); var underlyingType = memberType; var isValueType = memberType.GetTypeInfo().IsValueType; var isEnum = memberType.GetTypeInfo().IsEnum; var isNullable = Nullable.GetUnderlyingType(memberType) != null; if (isNullable) { underlyingType = Nullable.GetUnderlyingType(memberType); isEnum = underlyingType.GetTypeInfo().IsEnum; } var isString = underlyingType == typeof(string); // stack is now [parameters][parameters][parameter][parameter].DbType={DbType} il.Emit(OpCodes.Dup); LoadInt32(il, (int)dbType); il.EmitCall(OpCodes.Callvirt, typeof(IDataParameter).GetProperty(nameof(IDataParameter.DbType)).GetSetMethod(), null); // stack is now [parameters][parameters][parameter][parameter].Direction={ParameterDirection.Input} il.Emit(OpCodes.Dup); LoadInt32(il, (int)ParameterDirection.Input); il.EmitCall(OpCodes.Callvirt, typeof(IDataParameter).GetProperty(nameof(IDataParameter.Direction)).GetSetMethod(), null); //byte,double,float,int,long,sbyte,short,string,Type il.Emit(OpCodes.Dup); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldstr, colMapper.Key); il.Emit(OpCodes.Call, typeof(KeyValuePair <string, object>).GetProperty(nameof(KeyValuePair <string, object> .Value)).GetGetMethod()); // stack is now [parameters][parameters][parameter][parameter][value] if (memberType.GetTypeInfo().IsValueType) { il.Emit(OpCodes.Box, memberType); if (memberType.GetTypeInfo().IsEnum&& memberType == typeof(string)) { // stack is now [parameters][parameters][parameter][parameter][int-value][enum-type] il.Emit(OpCodes.Ldtoken, underlyingType); il.EmitCall(OpCodes.Call, typeof(Type).GetMethod(nameof(Type.GetTypeFromHandle)), null); // stack is now [parameters][parameters][parameter][parameter][int-value][enum-type] il.EmitCall(OpCodes.Call, typeof(RepositoryHelper).GetMethod(nameof(RepositoryHelper.GetEnumName), BindingFlags.Static | BindingFlags.Public), null); il.EmitCall(OpCodes.Callvirt, typeof(IDataParameter).GetProperty(nameof(IDataParameter.Value)).GetSetMethod(), null); //直接设置长度为100,枚举值都不会超过100个字符,避免了做类似下面的复杂逻辑操作 il.Emit(OpCodes.Dup); LoadInt32(il, 100); il.EmitCall(OpCodes.Callvirt, typeof(IDbDataParameter).GetProperty(nameof(IDbDataParameter.Size)).GetSetMethod(), null); #region 获取字符串长度,设置长度 //// stack is now [parameters][parameters][parameter][parameter][string or dbNull] //il.Emit(OpCodes.Dup); //il.Emit(OpCodes.Isinst, typeof(DBNull)); //// stack is now [target][target][value][DBNull or null] //Label dbNullLabel = il.DefineLabel(); //il.Emit(OpCodes.Brtrue_S, dbNullLabel); ////非空字符串 //var iLocIndex = il.DeclareLocal(typeof(string)).LocalIndex; //il.Emit(OpCodes.Dup); //il.Emit(OpCodes.Castclass, typeof(string)); //il.Emit(OpCodes.Stloc, iLocIndex); //il.EmitCall(OpCodes.Callvirt, typeof(IDataParameter).GetProperty(nameof(IDataParameter.Value)).GetSetMethod(), null); //// stack is now [parameters][parameters][parameter] ////设置长度 //il.Emit(OpCodes.Dup); //il.Emit(OpCodes.Ldloc, iLocIndex); //il.EmitCall(OpCodes.Callvirt, typeof(string).GetProperty(nameof(string.Length)).GetGetMethod(), null); //// stack is now [parameters][parameters][parameter][string-length] //il.EmitCall(OpCodes.Callvirt, typeof(IDbDataParameter).GetProperty(nameof(IDbDataParameter.Size)).GetSetMethod(), null); //Label allDoneLabel = il.DefineLabel(); //il.Emit(OpCodes.Br_S, allDoneLabel); //il.MarkLabel(dbNullLabel); //il.EmitCall(OpCodes.Callvirt, typeof(IDataParameter).GetProperty(nameof(IDataParameter.Value)).GetSetMethod(), null); //il.MarkLabel(allDoneLabel); #endregion } else { if (isNullable) { il.Emit(OpCodes.Dup); Label notNullLabel = il.DefineLabel(); il.Emit(OpCodes.Brtrue_S, notNullLabel); // stack is now [parameters][parameters][parameter] il.Emit(OpCodes.Pop); il.Emit(OpCodes.Ldsfld, typeof(DBNull).GetField(nameof(DBNull.Value))); il.MarkLabel(notNullLabel); } // stack is now [parameters][parameters][parameter][parameter][object-value] il.EmitCall(OpCodes.Callvirt, typeof(IDataParameter).GetProperty(nameof(IDataParameter.Value)).GetSetMethod(), null); } } else { // stack is now [parameters][parameters][parameter] il.Emit(OpCodes.Dup); Label notNullLabel = il.DefineLabel(); il.Emit(OpCodes.Brtrue_S, notNullLabel); // stack is now [parameters][parameters][parameter][parameter] il.Emit(OpCodes.Pop); il.Emit(OpCodes.Ldsfld, typeof(DBNull).GetField(nameof(DBNull.Value))); // stack is now [parameters][parameters][parameter][parameter][DBNull] il.EmitCall(OpCodes.Callvirt, typeof(IDataParameter).GetProperty(nameof(IDataParameter.Value)).GetSetMethod(), null); Label allDoneLabel = il.DefineLabel(); il.Emit(OpCodes.Br_S, allDoneLabel); //不为空 il.MarkLabel(notNullLabel); int?stringIndex = null; if (isString) { il.Emit(OpCodes.Dup); // stack is now [parameters][parameters][parameter][parameter][string][string] il.EmitCall(OpCodes.Callvirt, typeof(string).GetProperty(nameof(string.Length)).GetGetMethod(), null); LoadInt32(il, 4000); il.Emit(OpCodes.Cgt); // [string] [0 or 1] Label isLong = il.DefineLabel(), lenDone = il.DefineLabel(); il.Emit(OpCodes.Brtrue_S, isLong); LoadInt32(il, 4000); // [string] [4000] il.Emit(OpCodes.Br_S, lenDone); il.MarkLabel(isLong); LoadInt32(il, -1); // [string] [-1] il.MarkLabel(lenDone); stringIndex = il.DeclareLocal(typeof(int)).LocalIndex; il.Emit(OpCodes.Stloc_S, (byte)stringIndex); } il.EmitCall(OpCodes.Callvirt, typeof(IDataParameter).GetProperty(nameof(IDataParameter.Value)).GetSetMethod(), null); // stack is now [parameters][parameters][parameter] if (isString) { il.Emit(OpCodes.Dup); // stack is now [parameters][parameters][parameter][parameter].Size=len(string) il.Emit(OpCodes.Stloc_S, (byte)stringIndex); il.EmitCall(OpCodes.Callvirt, typeof(IDbDataParameter).GetProperty(nameof(IDbDataParameter.Size)).GetSetMethod(), null); // stack is now [parameters][parameters][parameter] } il.MarkLabel(allDoneLabel); } // stack is now [parameters][parameters].Add([parameter]) il.EmitCall(OpCodes.Callvirt, typeof(IList).GetMethod(nameof(IList.Add)), null); il.Emit(OpCodes.Pop); // stack is now [parameters] }
public EntityMapper(Type entityType) { this.EntityType = entityType; this.TableName = entityType.Name; this.FieldPrefix = String.Empty; this.MemberMappers = new Dictionary <string, MemberMapper>(); this.PrimaryKeys = new List <MemberMapper>(); var tableAttr = entityType.GetTypeInfo().GetCustomAttribute <TableAttribute>(); if (tableAttr != null) { if (!String.IsNullOrEmpty(tableAttr.TableName)) { this.TableName = tableAttr.TableName; } this.FieldPrefix = tableAttr.FieldPrefix; } var properties = entityType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Where(p => p.GetIndexParameters().Length == 0); foreach (var prop in properties) { MemberMapper colMapper = new MemberMapper(); if (prop.GetCustomAttribute <IgnoreAttribute>() != null) { continue; } colMapper.FieldName = this.FieldPrefix + prop.Name; colMapper.GetMethodInfo = prop.GetGetMethod(true); colMapper.MemberName = prop.Name; colMapper.MemberType = prop.PropertyType; colMapper.DbType = DbTypeMap.LookupDbType(prop.PropertyType); colMapper.UnderlyingType = prop.PropertyType; colMapper.IsValueType = prop.PropertyType.GetTypeInfo().IsValueType; colMapper.IsEnum = prop.PropertyType.GetTypeInfo().IsEnum; colMapper.IsNullable = Nullable.GetUnderlyingType(colMapper.MemberType) != null; if (colMapper.IsNullable) { colMapper.UnderlyingType = Nullable.GetUnderlyingType(colMapper.MemberType); colMapper.IsEnum = colMapper.UnderlyingType.GetTypeInfo().IsEnum; } var toUnderlyingType = colMapper.UnderlyingType; var keyAttr = prop.GetCustomAttribute <PrimaryKeyAttribute>(); if (keyAttr != null) { if (!String.IsNullOrEmpty(keyAttr.FieldName)) { colMapper.FieldName = keyAttr.FieldName; } if (keyAttr.FieldType != null) { toUnderlyingType = keyAttr.FieldType; colMapper.DbType = DbTypeMap.LookupDbType(keyAttr.FieldType); } colMapper.IsPrimaryKey = true; colMapper.IsAutoIncrement = keyAttr.AutoIncrement; this.PrimaryKeys.Add(colMapper); } else { colMapper.IsPrimaryKey = false; } var colAttr = prop.GetCustomAttribute <ColumnAttribute>(); if (colAttr != null) { if (!String.IsNullOrEmpty(colAttr.FieldName)) { colMapper.FieldName = colAttr.FieldName; } if (colAttr.FieldType != null) { toUnderlyingType = colAttr.FieldType; colMapper.DbType = DbTypeMap.LookupDbType(colAttr.FieldType); colMapper.IsAutoIncrement = colAttr.AutoIncrement; } } colMapper.IsString = colMapper.UnderlyingType == typeof(string) || toUnderlyingType == typeof(string); colMapper.IsLinqBinary = colMapper.UnderlyingType.FullName == DbTypeMap.LinqBinary; this.MemberMappers.Add(prop.Name, colMapper); } }