/// <summary> /// Determines whether the specified <see cref="System.Object" />, is equal to this instance. /// </summary> /// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param> /// <returns> /// <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>. /// </returns> public override bool Equals(object obj) { BuilderKey builderKey = obj as BuilderKey; if (builderKey == null) { return(false); } if (_dbType != builderKey._dbType) { return(false); } if (_destinationType != builderKey._destinationType) { return(false); } if (this._dataRecordNames.Count != builderKey._dataRecordNames.Count) { return(false); } for (int i = 0; i < _dataRecordNames.Count; i++) { if (this._dataRecordNames[i] != builderKey._dataRecordNames[i]) { return(false); } } return(true); }
public delegate object Build(IDataRecord dataRecord);//最终执行动态方法的一个委托 /// <summary> /// emit绑定IDataRecord到实体类集合 /// </summary> /// <param name="dataRecord">IDataRecord</param> /// <param name="destinationType">实体类类型</param> /// <param name="dbType">数据库类型(为兼容不同数据库,待完善)</param> /// <returns></returns> public static Build CreateBuilder(IDataRecord dataRecord, Type destinationType, DataBaseType dbType) { BuilderKey builderKey = new BuilderKey(destinationType, dataRecord, dbType); Build dynamicBuilder = (Build)cache[builderKey]; if (dynamicBuilder != null) { return(dynamicBuilder); } DynamicMethod method = new DynamicMethod("DynamicCreate", destinationType, new Type[] { typeof(IDataRecord) }, destinationType, true); ILGenerator il = method.GetILGenerator(); LocalBuilder result = il.DeclareLocal(destinationType); il.Emit(OpCodes.Newobj, destinationType.GetConstructor(Type.EmptyTypes)); //创建目标类型实例 il.Emit(OpCodes.Stloc, result); il.BeginExceptionBlock(); //try for (int i = 0; i < dataRecord.FieldCount; i++) { PropertyInfo propertyInfo = destinationType.GetProperty(dataRecord.GetName(i), BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase); if (propertyInfo != null && propertyInfo.GetSetMethod(true) != null) { Label endIfLabel = il.DefineLabel(); /* The code then loops through the fields in the data reader, finding matching properties on the type passed in. * When a match is found, the code checks to see if the value from the data reader is null. */ il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Callvirt, isDBNullMethod); il.Emit(OpCodes.Brtrue, endIfLabel); //If the value in the data reader is not null, the code sets the value on the object. il.Emit(OpCodes.Ldloc, result); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Callvirt, getValueMethod); Type propertyType = propertyInfo.PropertyType; Type nullableUnderlyingType = Nullable.GetUnderlyingType(propertyType); Type propertyBaseType = nullableUnderlyingType != null ? nullableUnderlyingType : propertyType; if (propertyType == charType) //char类型特殊 { il.EmitCall(OpCodes.Call, getCharValueMethod, null); } else if (propertyType == byteArrayType) //byte[] { il.Emit(OpCodes.Castclass, dataRecord.GetFieldType(i)); } else if (propertyType.FullName == LinqBinary) { il.Emit(OpCodes.Unbox_Any, byteArrayType); il.Emit(OpCodes.Newobj, propertyType.GetConstructor(new Type[] { byteArrayType })); } else if (dbType == DataBaseType.Oracle && propertyBaseType == boolType) //oracle数据库bool类型转换 { il.EmitCall(OpCodes.Call, getOracleBoolValueMethod, null); } else if (propertyBaseType == guidType && (dbType == DataBaseType.OleDb || dbType == DataBaseType.SQLite)) { //支持access或sqlite数据库是Guid类型和字符串类型保存的Guid类型数据转换 if (dataRecord.GetFieldType(i) != stringType) { il.Emit(OpCodes.Call, convertToString); } il.Emit(OpCodes.Newobj, propertyBaseType.GetConstructor(new Type[] { stringType })); //转为Guid类型 if (nullableUnderlyingType != null) //赋值到Nullable类型 { il.Emit(OpCodes.Newobj, propertyType.GetConstructor(new Type[] { propertyBaseType })); } } else { if (nullableUnderlyingType != null) //可空类型(Nullable) { if (propertyBaseType.IsEnum) { il.Emit(OpCodes.Call, convertToInt32); } else { MethodInfo convertMethod = typeof(Convert).GetMethod("To" + propertyBaseType.Name, new Type[] { objectType }); if (convertMethod != null) { il.Emit(OpCodes.Call, convertMethod);//将数据库类型强制转换为实体类定义的类型 } else { il.Emit(OpCodes.Unbox_Any, propertyBaseType);//Guid类型无Convert转换方法 } } il.Emit(OpCodes.Newobj, propertyType.GetConstructor(new Type[] { propertyBaseType })); } else { if (propertyBaseType.IsEnum) //支持数据库是char和int类型的枚举转换 { il.Emit(OpCodes.Call, convertToString); //先转为string类型,防止特殊情况,如数据库是char类型存储 il.Emit(OpCodes.Call, convertToInt32); //再转为int类型 } else { MethodInfo convertMethod = typeof(Convert).GetMethod("To" + propertyBaseType.Name, new Type[] { objectType }); if (convertMethod != null) { il.Emit(OpCodes.Call, convertMethod);//强制转换,可能会出现类型转换异常 } else { il.Emit(OpCodes.Unbox_Any, dataRecord.GetFieldType(i));//Guid } } } } /*The last part of the code returns the value of the local variable*/ il.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod(true)); il.MarkLabel(endIfLabel); } } il.BeginCatchBlock(typeof(InvalidCastException)); //catch il.Emit(OpCodes.Rethrow); il.BeginCatchBlock(typeof(System.Exception)); //catch il.Emit(OpCodes.Rethrow); il.EndExceptionBlock(); //end catch il.Emit(OpCodes.Ldloc, result); il.Emit(OpCodes.Ret); dynamicBuilder = (Build)method.CreateDelegate(typeof(Build)); cache[builderKey] = dynamicBuilder; return(dynamicBuilder); }