如何用反射创建基本类型?
小弟对动态创建比较陌生,希望得到大家帮助。需求是这样的:数据库各个表都有value这一列,但是value的类型不确定,可能是double,string,int,但肯定都是基本类型。
不知道怎么才能把这些value在c#中转成对应的基本类型?
是否要用到反射?
--------------------编程问答-------------------- 官方
http://www.tracefact.net/CLR-and-Framework/Reflection-Part4.aspx --------------------编程问答--------------------
我试过用Assembly和Activator创建,按我的理解出来的还是object,好像也必须强制类型转换,不能直接用。
我想做的是比如给 "double" 和 “123.0” 直接能得到 double 型的 123.0,不知道有没有这样的方法。 --------------------编程问答-------------------- 这和反射没毛的关系。 --------------------编程问答-------------------- --------------------编程问答--------------------
那请教一下有啥思路么? --------------------编程问答-------------------- 没必要用反射,直接用Convert.ToInt32,Convert.ToString,Convert.ToDouble就可以, --------------------编程问答-------------------- 数据库的行读取到DataTable中,.Net已经帮你反射好了, --------------------编程问答-------------------- 的确和反射一点关系都没有。
第一,通过用sql读取数据表字段类型(当然你也可以采取别的方法)
SELECT name AS TableName FROM sysobjects WHERE (xtype = 'U') AND (name <> 'dtproperties') ORDER BY name
--
SELECT sysobjects.name AS TableName, syscolumns.name AS FieldName, systypes.name AS FieldType
FROM syscolumns INNER JOIN
sysobjects ON syscolumns.id = sysobjects.id AND sysobjects.xtype = 'U' AND
sysobjects.name <> 'dtproperties' INNER JOIN
systypes ON syscolumns.xtype = systypes.xtype AND
syscolumns.xusertype = systypes.xusertype
第二,转换:
--------------------编程问答-------------------- 看不懂你说的时候什么。或者,你可能犯了一个最简单错误。
/// <summary>
/// 将字段类型抓换为.Net可识别的类型
/// </summary>
/// <param name="type">数据库字段类型名称</param>
/// <returns>.Net类型名称</returns>
private string GetNetType(string type)
{
switch (type.ToLower())
{
case "bigint":
return SqlDbType.BigInt.ToString();
case "binary":
return SqlDbType.Binary.ToString();
case "bit":
return SqlDbType.Bit.ToString();
case "char":
return SqlDbType.Char.ToString();
case "datetime":
return SqlDbType.DateTime.ToString();
case "decimal":
return SqlDbType.Decimal.ToString();
case "float":
return SqlDbType.Float.ToString();
case "image":
return SqlDbType.Image.ToString();
case "int":
return SqlDbType.Int.ToString();
case "money":
return SqlDbType.Money.ToString();
case "nchar":
return SqlDbType.NChar.ToString();
case "ntext":
return SqlDbType.NText.ToString();
case "numeric":
return SqlDbType.Decimal.ToString();
case "nvarchar":
return SqlDbType.NVarChar.ToString();
case "real":
return SqlDbType.Real.ToString();
case "smalldatetime":
return SqlDbType.SmallDateTime.ToString();
case "smallint":
return SqlDbType.SmallInt.ToString();
case "smallmoney":
return SqlDbType.SmallMoney.ToString();
case "sql_variant":
return SqlDbType.Variant.ToString();
case "text":
return SqlDbType.Text.ToString();
case "timestamp":
return SqlDbType.Timestamp.ToString();
case "tinyint":
return SqlDbType.TinyInt.ToString();
case "uniqueidentifier":
return SqlDbType.UniqueIdentifier.ToString();
case "varbinary":
return SqlDbType.VarBinary.ToString();
case "varchar":
return SqlDbType.VarChar.ToString();
case "xml":
return SqlDbType.Xml.ToString();
default:
return SqlDbType.Udt.ToString();
}
}
所谓一个
object value;这个变量所引用的对象的“基本类型”,它本身就是基本类型。比如说它引用一个int,那么value它本身就引用一个int;比如说它引用一个string,那么value它本身就是引用一个string。你试一试代码
object a = 1234;
a = "1234";
Type type=a.GetType();
那么你怎么会弄成什么“我要转换一个基本类型”这种话?我想大多是你自己都没有搞明白编程跟执行的区别吧。你想说明value所引用的对象的类型是不确定的,又想让我们给你写一个代码你好在声明时就去写下value的“基本类型”,这就是一个不可能完成的悖论,是个难以解释通顺的任务。 --------------------编程问答-------------------- 在你使用ado.net的DbDataReader读取一个字段,例如 reader["value"] 的时候,它声明的是 object 类型,而它引用的就是基本类型。还要怎样“转换”呢? --------------------编程问答--------------------
呃,可能我之前表述有问题,有些概念也不是很清。
数据已经读到DataTable里了,Convert我也知道。之前比如知道字段“Id”是整型那就直接
int i = (int)table.Rows[0]["Id"]可以的。
但是假设现在“Id”的类型要运行时才知道,那上面那行代码的功能要怎么实现? --------------------编程问答--------------------
代码我试了,a.GetType()FullName是System.String. 这个a也没法直接当string来用,比如用Split方法,不还得强制类型转换 (string)a 么。
数据库我也不是很熟,我读到datatable里的值都是object,都要用比如
int id = (int)table.Rows[0]["Id"]这样强制类型转换。但是这只能是我事先知道"Id"是整型才能这么写啊,如果字段“value”类型是不知道的情况下,我编码的时候应该怎么写实现跟上面一样的效果,比如让整型就是整形,字符串就是字符串?我能想到的只有用个switch case,但感觉这样太难看了,不知道有没有其他简洁的实现方法。
--------------------编程问答--------------------
switch case其实是最简单的实现方法,当然你可以用多态性代替switch case,
定义一个基类,比如
abstract class BClass
{
private static LinkedList<BClass> m_lstRegisteredClass=new LinkedList<BClass>();
public abstract void Process(object value);
public abstract Type GetValueType();
public static void RegisterClass(BClass rClass)
{
lstRegisteredClass.AddLast(rClass);
}
public static BClass SelectInstance(object value)
{
foreach(BClass rClass in lstRegisteredClass)
{
if (value.GetType()==rClass.GetValueType())
return rClass;
}
return null;
}
}
然后把case里的内容放在派生类的Process重载中,switch的内容改为:
BClass rClass=BClass.SelectInstance(value);
rClass.Process(value);
这样看起来很简洁,
不过首先要注册BClass派生类,也可以把BClass派生类写在xml文件中,让BClass通过反射创建派生类,
补充:.NET技术 , C#