2016.5.23 用反射技术为实体类变量赋值、取值
clobj是任意一个数据库表对应的实体类空白实例 TERMINAL_PRO clobj= new TERMINAL_PRO();
DataRow row = dtt.Rows[0];
Type t = clobj.GetType();
foreach (PropertyInfo pi in t.GetProperties()) //不用考虑属性的类型
{
string name = pi.Name; //获得此属性名称
if (dtt.Columns.Contains(name))
{
object ob = row[name];
pi.SetValue(clobj, ob.IsEmptyOrNull() ? null : Convert.ChangeType(ob, pi.PropertyType), null);
}
}
至此clobj赋值完成,各种类型的变量根据DataRow类型完成赋值
pi.SetValue(pro,value,null) 将value赋值给pro实例的pi对应属性,value和pi类型必须统一,所以1要判断是否null,2要进行类型转换Convert.ChangeType(ob, pi.PropertyType)
//简化insert into 及反射赋值技术
string sql_insert = string.Format("insert into {0}.{1} ( ", AisLogical.dbuser, "TERMINAL_PRO_DOUBLE");
string sql_value = string.Format("values ( ");
Type t = pro.GetType();
foreach (PropertyInfo pi in t.GetProperties())
{
string name = pi.Name; //获得此属性名称
object value = pi.GetValue(pro, null);//获得此属性值
sql_insert += name + ", ";
if (pi.PropertyType == typeof(string)) //属性的类型判断
{
sql_value += string.Format(" '{0}', ", value);
}
else
sql_value += value+",";
}
pi.GetValue(pro, null); 获取pro对象对应pi属性的值。
此外,函数调用中的ref关键字只对简单变量有效,如果是实例作为参数,即使不加ref,调用结束后此实例仍然保留了函数中的赋值过程。原理是,如果不用ref修饰参数变量,调用函数就复制此参数进入函数调用。但对实例参数,这种拷贝是浅拷贝,所以跟带了ref前缀效果一样。
通用赋值函数:
//通过实体类为某窗体上的对应控件赋值
//赋值条件:实体类名称与该控件名称后两位相同
public static void RefreshControlThrObject(object obj,Control frm)
{
Type t = obj.GetType();
foreach (PropertyInfo pi in t.GetProperties()) //不用考虑属性的类型
{
string name = pi.Name; //获得此属性名称
object value = pi.GetValue(obj, null);//数据库该项原值
value = value.Nvlstr(); //将空值转换为""
//自动为界面上的控件赋值
foreach (Control ctr in frm.Controls)
{
if (ctr.Name.Substring(2) == name) //控件名称与属性名相同,只是前面多两个代表控件类型的字母cb、tb等
{
if (ctr.GetType().Name == "ComboBox")
{
if (((ComboBox)ctr).DropDownStyle == ComboBoxStyle.DropDown) //可编辑的combbox
((ComboBox)ctr).Text = value.ToString();
else
((ComboBox)ctr).SelectedValue = value;
}
else if (ctr.GetType().Name.Contains("TextBox"))
((TextBox)ctr).Text = value.ToString();
else if (ctr.GetType().Name == "CheckBox")
{
if (value.ToString() == "Y" || value.ToString() == "1") //数据库中表示逻辑是否一般用数字0或1表示,但424中一般用Y,N表示,所以这里要兼容这两种写法
((CheckBox)ctr).Checked = true;
else
((CheckBox)ctr).Checked = false;
}
break;
}
}
}
}
再次补充:下面的补充有缺陷,当需要变更实体类成员类型时,set,get无能为力。所以最好的办法还是添加sql语句列,同时增加实体类成员。
补充:利用Set Get为实体类灵活赋值
利用实体类可以快速为控件赋值,但有时控件如果直接显示数据库值不太直观,想对字段进行转换后再显示。如果在sql脚本中添加新列,则还要在对应实体类中添加新成员。
然而,通过在实体类中写上 set get可实现SQL语句还是最简单的select * ,只不过在为实体类成员赋值时用set get改变值的表现方式。
方法:在需要变形的成员前,新加一内部成员 可以_写列名前面表示内部成员。
代码:
public string _CODE_FIR;
/// <summary>
/// 所在情报区编号
/// </summary>
public string CODE_FIR
{
get
{
return _CODE_FIR;
}
set
{
if (value == "ZBPE") _CODE_FIR = "ZBPE(北京)";
else if (value == "ZGZU") _CODE_FIR = "ZGZU(广州)";
else if (value == "ZHWH") _CODE_FIR = "ZHWH(武汉)";
else if (value == "ZJSA") _CODE_FIR = "ZJSA(三亚)";
else if (value == "ZLHW") _CODE_FIR = "ZLHW(兰州)";
else if (value == "ZPKM") _CODE_FIR = "ZPKM(昆明)";
else if (value == "ZSHA") _CODE_FIR = "ZSHA(上海)";
else if (value == "ZWUQ") _CODE_FIR = "ZWUQ(乌鲁木齐)";
else if (value == "ZYSH") _CODE_FIR = "ZYSH(沈阳)";
else _CODE_FIR = value;
}
}