Emit将DataReader自动映射到对象问题?

事理 2012-09-19 03:54:11
用Emit如何将数据库char类型转换char类型的枚举呢

char aa = '4';
int ss = Convert.ToInt32(aa);
TestIntEnum en = (TestIntEnum)ss;
string cc = en.ToString();
MessageBox.Show(cc);

public enum TestIntEnum
{
red = '1',
green = '2',
gray = '3',
black = '4'
}

就是用Emit如何实现上面代码一样过程,先将char类型转为int32,再强制转换为枚举类型即可

下面这样写会报公共语言库错误,不知道改如何改,麻烦知道的大侠帮忙看看。

Type memberType = propertyInfo.PropertyType;
Type nullUnderlyingType = Nullable.GetUnderlyingType(memberType);
Type baseType = nullUnderlyingType != null ? nullUnderlyingType : memberType;
MethodInfo convertMethod = typeof(Convert).GetMethod("ToInt32", new Type[] { typeof(object) });
il.Emit(OpCodes.Call, convertMethod);
il.Emit(OpCodes.Box, baseType);



...全文
336 20 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
事理 2012-09-20
  • 打赏
  • 举报
回复
非常感谢。
qldsrx 2012-09-20
  • 打赏
  • 举报
回复
邮件已发,新版完全支持.NET3.5,只要在项目的属性里添加条件编译符号“CSHARP30”即可。
事理 2012-09-20
  • 打赏
  • 举报
回复
嗯,懂了,谢谢。
qldsrx 2012-09-20
  • 打赏
  • 举报
回复
你要是愿意,先转换为char,然后转换为int,分2次转换,不过我是觉得没这个必要,为了这种特殊的枚举类型搞那么负责,完全没必要。
qldsrx 2012-09-20
  • 打赏
  • 举报
回复
没用,SqlDataReader里面没有char类型,所有char都会认为是string。
事理 2012-09-20
  • 打赏
  • 举报
回复
数据库是char(1)类型的
qldsrx 2012-09-20
  • 打赏
  • 举报
回复
另外解释下为什么你的ToInt32读不出来,但不报错,因为你从数据库取出来的是字符串“1”,而不是字符'1',对于字符串1的Convert.ToInt32,最终会转换为数字1而不是数字0x31,而你的enum定义了字符'1',实际缺失0x31,通过0x31查找1,怎么都查找不到啊。
事理 2012-09-20
  • 打赏
  • 举报
回复
看来也只能这样了
qldsrx 2012-09-20
  • 打赏
  • 举报
回复
最佳做法是,修改enum的定义,不规范的定义不要出现,而且你那种定义根本没有任何意义,enum是不能对应char的,最终是理解为int类型。
qldsrx 2012-09-20
  • 打赏
  • 举报
回复
定义不规范,怎么写通用代码?如果你强制转换是可以,但这不是规范的做法,enum规定了不能用char,你一定要用char的Ascii码去转换,这就是不规范做法,显然不能做到通用代码处理里面,你单独定制一个方法是可以,否则遇到标准的enum类型就无法转换了。
事理 2012-09-20
  • 打赏
  • 举报
回复
模拟emit现在是这样写的,但是读取出来不能转换,很难弄啊

var local = il.DeclareLocal(typeof(int));//创建一个Int局部变量
var local2 = il.DeclareLocal(baseType);//创建一个枚举局部变量
il.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToInt32", new Type[] { typeof(object) }));
il.Emit(OpCodes.Stloc, local);
il.Emit(OpCodes.Ldloc, local);
il.Emit(OpCodes.Box, baseType);
il.Emit(OpCodes.Stloc, local2);
il.Emit(OpCodes.Ldloc, local2);

事理 2012-09-20
  • 打赏
  • 举报
回复
那有没有办法解决呢?下面代码可以实现转换,在emit中不能实现该过程吗?
char aa = '4';
int ss = Convert.ToInt32(aa);
TestIntEnum en = (TestIntEnum)ss;
string cc = en.ToString();
MessageBox.Show(cc);
qldsrx 2012-09-20
  • 打赏
  • 举报
回复
正确的枚举定义应该这样:
public enum TestIntEnum
{
red = 1,
green = 2,
gray = 3,
black = 4
}

将单引号去掉。
qldsrx 2012-09-20
  • 打赏
  • 举报
回复
你那个例子里面的枚举,其实最终是这样的:
public enum TestIntEnum : int
{
black = 0x34,
gray = 0x33,
green = 50,
red = 0x31
}
如果你数据库里面是字符串的1、2、3、4,而不是数值型的1、2、3、4,那么当你要将其转换到枚举类型的时候,就会用前者“black”、“gray”、“green”、“red”去对应,那么你的字符1、2、3、4就对应不上了。

请仔细看看MSDN上的说明,枚举不支持字符类型,准许使用的枚举类型有 byte、 sbyte、 short、 ushort、 int、 uint、 long 或 ulong,其中是不包含char的。
事理 2012-09-19
  • 打赏
  • 举报
回复
qin_shili@qq.com谢谢哈
qldsrx 2012-09-19
  • 打赏
  • 举报
回复
准许使用的枚举类型有 byte、 sbyte、 short、 ushort、 int、 uint、 long 或 ulong, char是不允许的,编译器应该是自动转换到Uncode码值上面去了,char是二字节,等同于short的长度。
另外缓存是有的,你没仔细看,那个缓存是在外部调用的时候处理的,GetTypeDeserializer内部不需要缓存,人家缓存的考虑比你周全。

如果想要第二版的SqlMapper,可以留个邮箱,提前发下,不过以后还有可能会改动。
事理 2012-09-19
  • 打赏
  • 举报
回复
il.Emit(OpCodes.Unbox_Any, baseType);
il.Emit(OpCodes.Newobj, memberType.GetConstructor(new[] { nullUnderlyingType }));

整形的枚举这样可以出现red,green结果,但是char不行,纠结了很久。
事理 2012-09-19
  • 打赏
  • 举报
回复

前辈又是你回答我啊。看了SqlMapper的代码,我把那些条件也都加上了,不过枚举希望能够实现上面的效果,因为要绑定到dataGridView1,如果转换的值不是red、green,而是1,2这样的值就会报错。

还有SqlMapper貌似没有加上缓存哦


private class BuilderKey
{
private readonly List<string> _dataRecordNames;
private readonly Type _destinationType;

public BuilderKey(Type destinationType, IDataRecord record)
{
_destinationType = destinationType;
_dataRecordNames = new List<string>(record.FieldCount);
for (int i = 0; i < record.FieldCount; i++)
{
_dataRecordNames.Add(record.GetName(i));
}
}

public override int GetHashCode()
{
int hash = _destinationType.GetHashCode();
foreach (var name in _dataRecordNames)
{
hash = hash * 37 + name.GetHashCode();
}
return hash;
}

public override bool Equals(object obj)
{
var builderKey = obj as BuilderKey;
if (builderKey == null)
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;
}
}
}

private static Hashtable cache = Hashtable.Synchronized(new Hashtable());//缓存

BuilderKey builderKey = new BuilderKey(destinationType, dataRecord);
DynamicBuilder<T> dynamicBuilder = (DynamicBuilder<T>)cache[builderKey];
if (dynamicBuilder != null)
return dynamicBuilder;
dynamicBuilder = new DynamicBuilder<T>();
...

dynamicBuilder.handler = (Load)method.CreateDelegate(typeof(Load));
cache[builderKey] = dynamicBuilder;

可以性能会有更一步提高哦。
qldsrx 2012-09-19
  • 打赏
  • 举报
回复
哪里用得着那么复杂啊,我有一套完整的转换代码,只不过未公开过,以前曾公开过一份SqlMapper.cs的代码文件,里面有枚举的转换,但只能支持字符串到枚举的转换,如:字符串“red”可以转换到TestIntEnum.red上面,对于数值型类型的没包含在里面,第二版SqlMapper尚未发布,那里面都全的。

下面是第一版的SqlMapper的地址:http://blog.csdn.net/qldsrx/article/details/7452346
事理 2012-09-19
  • 打赏
  • 举报
回复
好难啊

111,094

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧