提交 236a948d 编写于 作者: M mgravell

parse enums from string, ala L2S

上级 1f7d2be3
......@@ -849,6 +849,11 @@ private static int ExecuteCommand(IDbConnection cnn, IDbTransaction tranaction,
return (T)val;
};
}
static readonly MethodInfo
enumParse = typeof(Enum).GetMethod("Parse", new Type[] { typeof(Type), typeof(string), typeof(bool) }),
getItem = typeof(IDataRecord).GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p => p.GetIndexParameters().Any() && p.GetIndexParameters()[0].ParameterType == typeof(int))
.Select(p => p.GetGetMethod()).First();
public static Func<IDataReader, T> GetClassDeserializer<T>(
#if CSHARP30
......@@ -863,6 +868,7 @@ private static int ExecuteCommand(IDbConnection cnn, IDbTransaction tranaction,
var il = dm.GetILGenerator();
il.DeclareLocal(typeof(int));
il.DeclareLocal(typeof(T));
bool haveEnumLocal = false;
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Stloc_0);
var properties = typeof(T)
......@@ -896,11 +902,6 @@ private static int ExecuteCommand(IDbConnection cnn, IDbTransaction tranaction,
select new { Name = n, Property = prop, Field = field }
).ToList();
var getItem = typeof(IDataRecord).GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p => p.GetIndexParameters().Any() && p.GetIndexParameters()[0].ParameterType == typeof(int))
.Select(p => p.GetGetMethod()).First();
int index = startBound;
il.BeginExceptionBlock();
......@@ -922,6 +923,7 @@ private static int ExecuteCommand(IDbConnection cnn, IDbTransaction tranaction,
il.Emit(OpCodes.Stloc_0);// stack is now [target][target][reader][index]
il.Emit(OpCodes.Callvirt, getItem); // stack is now [target][target][value-as-object]
il.Emit(OpCodes.Dup); // stack is now [target][target][value][value]
il.Emit(OpCodes.Isinst, typeof(DBNull)); // stack is now [target][target][value-as-object][DBNull or null]
il.Emit(OpCodes.Brtrue_S, isDbNullLabel); // stack is now [target][target][value-as-object]
......@@ -930,6 +932,50 @@ private static int ExecuteCommand(IDbConnection cnn, IDbTransaction tranaction,
Type memberType = item.Property != null ? item.Property.Type : item.Field.FieldType;
var nullUnderlyingType = Nullable.GetUnderlyingType(memberType);
var unboxType = nullUnderlyingType != null && nullUnderlyingType.IsEnum ? nullUnderlyingType : memberType;
if (unboxType.IsEnum)
{
if (!haveEnumLocal)
{
il.DeclareLocal(typeof(string));
haveEnumLocal = true;
}
Label isNotString = il.DefineLabel();
il.Emit(OpCodes.Dup); // stack is now [target][target][value][value]
il.Emit(OpCodes.Isinst, typeof(string)); // stack is now [target][target][value-as-object][string or null]
il.Emit(OpCodes.Dup);// stack is now [target][target][value-as-object][string or null][string or null]
il.Emit(OpCodes.Stloc_2); // stack is now [target][target][value-as-object][string or null]
il.Emit(OpCodes.Brfalse_S, isNotString); // stack is now [target][target][value-as-object]
il.Emit(OpCodes.Pop); // stack is now [target][target]
il.Emit(OpCodes.Ldtoken, unboxType); // stack is now [target][target][enum-type-token]
il.EmitCall(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"), null);// stack is now [target][target][enum-type]
il.Emit(OpCodes.Ldloc_2); // stack is now [target][target][enum-type][string]
il.Emit(OpCodes.Ldc_I4_1); // stack is now [target][target][enum-type][string][true]
il.EmitCall(OpCodes.Call, enumParse, null); // stack is now [target][target][enum-as-object]
il.Emit(OpCodes.Unbox_Any, unboxType); // stack is now [target][target][typed-value]
if (nullUnderlyingType != null)
{
il.Emit(OpCodes.Newobj, memberType.GetConstructor(new[] { nullUnderlyingType }));
}
if (item.Property != null)
{
il.Emit(OpCodes.Callvirt, item.Property.Setter); // stack is now [target]
}
else
{
il.Emit(OpCodes.Stfld, item.Field); // stack is now [target]
}
il.Emit(OpCodes.Br_S, finishLabel);
il.MarkLabel(isNotString);
}
il.Emit(OpCodes.Unbox_Any, unboxType); // stack is now [target][target][typed-value]
if (nullUnderlyingType != null && nullUnderlyingType.IsEnum)
{
......
......@@ -528,10 +528,28 @@ class TestEnumClass
{
public TestEnum? EnumEnum { get; set; }
}
class TestEnumClassNoNull
{
public TestEnum EnumEnum { get; set; }
}
public void TestEnumWeirdness()
{
connection.Query<TestEnumClass>("select null as [EnumEnum]");
connection.Query<TestEnumClass>("select cast(1 as tinyint) as [EnumEnum]");
connection.Query<TestEnumClass>("select null as [EnumEnum]").First().EnumEnum.IsEqualTo(null);
connection.Query<TestEnumClass>("select cast(1 as tinyint) as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
}
void Foo()
{
string s = "Bla";
var obj = new TestEnumClassNoNull();
obj.EnumEnum = (TestEnum)Enum.Parse(typeof(TestEnum), s, true);
}
public void TestEnumStrings()
{
connection.Query<TestEnumClassNoNull>("select 'BLA' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
connection.Query<TestEnumClassNoNull>("select 'bla' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
connection.Query<TestEnumClass>("select 'BLA' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
connection.Query<TestEnumClass>("select 'bla' as [EnumEnum]").First().EnumEnum.IsEqualTo(TestEnum.Bla);
}
public void TestSupportForParamDictionary()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册