110,499
社区成员
发帖
与我相关
我的任务
分享
internal class DynamicBuilder<T>
{
private static IDictionary<Type, Type> types = new Dictionary<Type, Type>();
private static readonly MethodInfo getValueMethod =
typeof(IDataRecord).GetMethod("get_Item", new Type[] { typeof(int) });
private static readonly MethodInfo isDBNullMethod =
typeof(IDataRecord).GetMethod("IsDBNull", new Type[] { typeof(int) });
private delegate T Load(IDataRecord dataRecord);
private Load handler;
private DynamicBuilder() { }
static DynamicBuilder()
{
types.Add(typeof(bool), typeof(Nullable<bool>));
types.Add(typeof(byte), typeof(Nullable<byte>));
types.Add(typeof(DateTime), typeof(Nullable<DateTime>));
types.Add(typeof(decimal), typeof(Nullable<decimal>));
types.Add(typeof(double), typeof(Nullable<double>));
types.Add(typeof(float), typeof(Nullable<float>));
types.Add(typeof(Guid), typeof(Nullable<Guid>));
types.Add(typeof(Int16), typeof(Nullable<Int16>));
types.Add(typeof(Int32), typeof(Nullable<Int32>));
types.Add(typeof(Int64), typeof(Nullable<Int64>));
}
public T Build(IDataRecord dataRecord)
{
return handler(dataRecord);
}
public static DynamicBuilder<T> CreateBuilder(IDataRecord dataRecord)
{
DynamicBuilder<T> dynamicBuilder = new DynamicBuilder<T>();
DynamicMethod method = new DynamicMethod("DynamicCreate", typeof(T),
new Type[] { typeof(IDataRecord) }, typeof(T), true);
ILGenerator generator = method.GetILGenerator();
LocalBuilder result = generator.DeclareLocal(typeof(T));
generator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes));
generator.Emit(OpCodes.Stloc, result);
for (int i = 0; i < dataRecord.FieldCount; i++)
{
PropertyInfo propertyInfo = typeof(T).GetProperty(dataRecord.GetName(i));
Label endIfLabel = generator.DefineLabel();
if (propertyInfo != null && propertyInfo.GetSetMethod() != null)
{
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldc_I4, i);
generator.Emit(OpCodes.Callvirt, isDBNullMethod);
generator.Emit(OpCodes.Brtrue, endIfLabel);
generator.Emit(OpCodes.Ldloc, result);
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldc_I4, i);
generator.Emit(OpCodes.Callvirt, getValueMethod);
bool isNullable = false;
if (propertyInfo.PropertyType.Name.ToLower().Contains("nullable"))
isNullable = true;
Type _type = dataRecord.GetFieldType(i);
if (isNullable)
generator.Emit(OpCodes.Unbox_Any, types[_type]);
else
generator.Emit(OpCodes.Unbox_Any, _type);
generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod());
generator.MarkLabel(endIfLabel);
}
}
generator.Emit(OpCodes.Ldloc, result);
generator.Emit(OpCodes.Ret);
dynamicBuilder.handler = (Load)method.CreateDelegate(typeof(Load));
return dynamicBuilder;
}
}
Type memberType = propertyInfo.PropertyType;
Type nullUnderlyingType = Nullable.GetUnderlyingType(memberType);
Type unboxType = nullUnderlyingType != null ? nullUnderlyingType : memberType;
if (unboxType == typeof(byte[]) || unboxType == typeof(string))
{
il.Emit(OpCodes.Castclass, memberType);
}
else
{
il.Emit(OpCodes.Unbox_Any, dataRecord.GetFieldType(i));
if (nullUnderlyingType != null)
{
il.Emit(OpCodes.Newobj, memberType.GetConstructor(new[] { nullUnderlyingType }));
}
}
Type memberType = propertyInfo.PropertyType;
Type nullUnderlyingType = Nullable.GetUnderlyingType(memberType);
Type unboxType = nullUnderlyingType != null ? nullUnderlyingType : memberType;
if (unboxType == typeof(byte[]) || unboxType == typeof(string))
{
generator.Emit(OpCodes.Castclass, memberType);
}
else
{
generator.Emit(OpCodes.Unbox_Any, unboxType);
if (nullUnderlyingType != null)
{
generator.Emit(OpCodes.Newobj, memberType.GetConstructor(new[] { nullUnderlyingType }));
}
}
else
{
generator.Emit(OpCodes.Unbox_Any, _type);
}
Type _type = dataRecord.GetFieldType(i);
Type memberType = propertyInfo.PropertyType;
Type nullUnderlyingType = Nullable.GetUnderlyingType(memberType);
//可空类型
if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
//if (nullUnderlyingType != null)
{
generator.Emit(OpCodes.Newobj, memberType.GetConstructor(new[] { nullUnderlyingType }));
//generator.Emit(OpCodes.Unbox_Any, nullUnderlyingType);
//generator.Emit(OpCodes.Newobj, propertyInfo.PropertyType.GetConstructor(new[] { nullUnderlyingType }));
}
else
{
generator.Emit(OpCodes.Unbox_Any, _type);
}
generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod());
generator.MarkLabel(endIfLabel);
var memberType = propertyInfo.PropertyType;
var nullUnderlyingType = Nullable.GetUnderlyingType(memberType);
var unboxType = nullUnderlyingType != null ? nullUnderlyingType : memberType;
generator.Emit(OpCodes.Newobj, memberType.GetConstructor(new[] { nullUnderlyingType }));