ASP.NET中使用反射将控件值与实体值相互映射
2008-05-24 16:25 xiaosonl 阅读(2930) 评论(6) 编辑 收藏 举报在ASP.NET中, 我们要获取控件的值, 或是给控件赋值, 一般都是Control.Property = Entity.Property, Entity.Property = Control.Property.
如果控件太多,这样写就显的繁琐,而且容易出错.
这种情况下, 使用反射, 把符合控件名和实体属性名相同的值相互映射,只要一行代码就可以完成操作了.
来看主要的两个方法签名:
/// <summary>
/// 将控件的值映射到实体
/// </summary>
/// <param name="container">映射的控件的容器控件</param>
/// <param name="obj">实体</param>
/// <param name="isContainChildren">是否遍历子控件</param>
/// <param name="controlIDFormat">控件ID的格式, {0}表示值的名称</param>
/// <param name="customMaps">自定义的[属性-值]映射规则, Key=控件属性名, Value=属性类型</param>
public static void ControlsToEntity(Control container, object entity, bool isContainChildren, string controlIDFormat, params KeyValuePair<string, Type>[] customMaps)
/// <summary>
/// 将实体属性值映射到控件
/// </summary>
/// <param name="entity">实体</param>
/// <param name="container">映射的控件的容器控件</param>
/// <param name="isContainChildren">是否遍历子控件</param>
/// <param name="idFormat">控件ID的格式, {0}表示值的名称</param>
/// <param name="customMaps">自定义的[属性-值]映射规则, Key=控件属性名, Value=属性类型</param>
public static void EntityToControls(object entity, Control container, bool isContainChildren, string controlIDFormat, params KeyValuePair<string, Type>[] customMaps)
/// 将控件的值映射到实体
/// </summary>
/// <param name="container">映射的控件的容器控件</param>
/// <param name="obj">实体</param>
/// <param name="isContainChildren">是否遍历子控件</param>
/// <param name="controlIDFormat">控件ID的格式, {0}表示值的名称</param>
/// <param name="customMaps">自定义的[属性-值]映射规则, Key=控件属性名, Value=属性类型</param>
public static void ControlsToEntity(Control container, object entity, bool isContainChildren, string controlIDFormat, params KeyValuePair<string, Type>[] customMaps)
/// <summary>
/// 将实体属性值映射到控件
/// </summary>
/// <param name="entity">实体</param>
/// <param name="container">映射的控件的容器控件</param>
/// <param name="isContainChildren">是否遍历子控件</param>
/// <param name="idFormat">控件ID的格式, {0}表示值的名称</param>
/// <param name="customMaps">自定义的[属性-值]映射规则, Key=控件属性名, Value=属性类型</param>
public static void EntityToControls(object entity, Control container, bool isContainChildren, string controlIDFormat, params KeyValuePair<string, Type>[] customMaps)
然后是测试用例, 不太容易理解, 见谅:
public class Entity
{
public bool CheckBoxControl { get; set; }
public string TextBoxControl { get; set; }
public string LabelControl { get; set; }
public object OtherControl { get; set; }
public int DropDownListControl { get; set; }
public int? ListBoxControl { get; set; }
public string CustomControl { get; set; }
}
public class Custom : Control
{
public string CustomProperty { get; set; }
}
[TestClass()]
public class ControlMappingTest
{
[TestMethod()]
public void TestEntityControlsMapping()
{
Entity entity = new Entity()
{
CheckBoxControl = true,
ListBoxControl = 1,
DropDownListControl = 1,
LabelControl = "LabelValue",
TextBoxControl = "TextBoxValue",
CustomControl = "CustomValue",
};
控件
bool isContainChildren = true;
//实体 -> 控件
KeyValuePair<string, Type> customMaps = new KeyValuePair<string, Type>("CustomProperty", typeof(string));
ControlMapping.EntityToControls(entity, container, isContainChildren, "_{0}", customMaps);
Assert.AreEqual(entity.CheckBoxControl, CheckBoxControl.Checked);
Assert.AreEqual(entity.TextBoxControl, TextBoxControl.Text);
Assert.AreEqual(entity.LabelControl, LabelControl.Text);
Assert.AreEqual(entity.DropDownListControl, Converters.ChangeType<int>(DropDownListControl.SelectedValue));
Assert.AreEqual(entity.ListBoxControl, Converters.ChangeType<int>(ListBoxControl.SelectedValue));
Assert.AreEqual(entity.CustomControl, CustomControl.CustomProperty);
//控件 -> 实体
entity = new Entity();
ControlMapping.ControlsToEntity(container, entity, isContainChildren, "_{0}", customMaps);
Assert.AreEqual(entity.CheckBoxControl, CheckBoxControl.Checked);
Assert.AreEqual(entity.TextBoxControl, TextBoxControl.Text);
Assert.AreEqual(entity.LabelControl, LabelControl.Text);
Assert.AreEqual(entity.DropDownListControl, Converters.ChangeType<int>(DropDownListControl.SelectedValue));
Assert.AreEqual(entity.ListBoxControl,Converters.ChangeType<int>( ListBoxControl.SelectedValue));
Assert.AreEqual(entity.CustomControl, CustomControl.CustomProperty);
}
}
{
public bool CheckBoxControl { get; set; }
public string TextBoxControl { get; set; }
public string LabelControl { get; set; }
public object OtherControl { get; set; }
public int DropDownListControl { get; set; }
public int? ListBoxControl { get; set; }
public string CustomControl { get; set; }
}
public class Custom : Control
{
public string CustomProperty { get; set; }
}
[TestClass()]
public class ControlMappingTest
{
[TestMethod()]
public void TestEntityControlsMapping()
{
Entity entity = new Entity()
{
CheckBoxControl = true,
ListBoxControl = 1,
DropDownListControl = 1,
LabelControl = "LabelValue",
TextBoxControl = "TextBoxValue",
CustomControl = "CustomValue",
};
控件
bool isContainChildren = true;
//实体 -> 控件
KeyValuePair<string, Type> customMaps = new KeyValuePair<string, Type>("CustomProperty", typeof(string));
ControlMapping.EntityToControls(entity, container, isContainChildren, "_{0}", customMaps);
Assert.AreEqual(entity.CheckBoxControl, CheckBoxControl.Checked);
Assert.AreEqual(entity.TextBoxControl, TextBoxControl.Text);
Assert.AreEqual(entity.LabelControl, LabelControl.Text);
Assert.AreEqual(entity.DropDownListControl, Converters.ChangeType<int>(DropDownListControl.SelectedValue));
Assert.AreEqual(entity.ListBoxControl, Converters.ChangeType<int>(ListBoxControl.SelectedValue));
Assert.AreEqual(entity.CustomControl, CustomControl.CustomProperty);
//控件 -> 实体
entity = new Entity();
ControlMapping.ControlsToEntity(container, entity, isContainChildren, "_{0}", customMaps);
Assert.AreEqual(entity.CheckBoxControl, CheckBoxControl.Checked);
Assert.AreEqual(entity.TextBoxControl, TextBoxControl.Text);
Assert.AreEqual(entity.LabelControl, LabelControl.Text);
Assert.AreEqual(entity.DropDownListControl, Converters.ChangeType<int>(DropDownListControl.SelectedValue));
Assert.AreEqual(entity.ListBoxControl,Converters.ChangeType<int>( ListBoxControl.SelectedValue));
Assert.AreEqual(entity.CustomControl, CustomControl.CustomProperty);
}
}
之后我又有了新的想法, 就是在中间加入一层Hash值, 这样就可以实现UI层的解藕, 即Control <=> Hash <=> Entity.
暂时只实现了Control <=> Hash :
/// <summary>
/// 将控件值映射到Hash表
/// </summary>
/// <param name="container">映射控件的容器控件</param>
/// <param name="isContainChildren">是否遍历子控件</param>
/// <param name="customMaps">自定义的控件属性</param>
public static Dictionary<string, object> ControlsToHash(Control container, bool isContainChildren, params string[] customProperties)
/// <summary>
/// 将Hash表值映射到控件
/// </summary>
/// <param name="hash">Hash键值对</param>
/// <param name="container">映射控件的容器控件</param>
/// <param name="isContainChildren">是否遍历子控件</param>
public static void HashToControls(Dictionary<string, object> hash, Control container, bool isContainChildren, params string[] customProperties)
/// 将控件值映射到Hash表
/// </summary>
/// <param name="container">映射控件的容器控件</param>
/// <param name="isContainChildren">是否遍历子控件</param>
/// <param name="customMaps">自定义的控件属性</param>
public static Dictionary<string, object> ControlsToHash(Control container, bool isContainChildren, params string[] customProperties)
/// <summary>
/// 将Hash表值映射到控件
/// </summary>
/// <param name="hash">Hash键值对</param>
/// <param name="container">映射控件的容器控件</param>
/// <param name="isContainChildren">是否遍历子控件</param>
public static void HashToControls(Dictionary<string, object> hash, Control container, bool isContainChildren, params string[] customProperties)
测试用例:
[TestMethod]
public void ControlsToHashAndHashToControlsTest()
{
测试数据准备
Dictionary<string, object> expectedHash = new Dictionary<string, object>();
expectedHash.Add("c_UserID", "1");
expectedHash.Add("c_UserName", "Xiaosonl");
expectedHash.Add("c_Age", "1");
expectedHash.Add("c_IsUsed", "True");
expectedHash.Add("c_RoleID", "2");
ControlMapping.HashToControls(expectedHash, container, true);
Dictionary<string, object> hash = ControlMapping.ControlsToHash(container, false);
Assert.AreEqual(false, hash.SerializeEqual(expectedHash));
hash = ControlMapping.ControlsToHash(container, true);
Assert.AreEqual(true, hash.SerializeEqual(expectedHash));
}
public void ControlsToHashAndHashToControlsTest()
{
测试数据准备
Dictionary<string, object> expectedHash = new Dictionary<string, object>();
expectedHash.Add("c_UserID", "1");
expectedHash.Add("c_UserName", "Xiaosonl");
expectedHash.Add("c_Age", "1");
expectedHash.Add("c_IsUsed", "True");
expectedHash.Add("c_RoleID", "2");
ControlMapping.HashToControls(expectedHash, container, true);
Dictionary<string, object> hash = ControlMapping.ControlsToHash(container, false);
Assert.AreEqual(false, hash.SerializeEqual(expectedHash));
hash = ControlMapping.ControlsToHash(container, true);
Assert.AreEqual(true, hash.SerializeEqual(expectedHash));
}
具体实现代码见FastDev.Web.ControlMapping类.
下载FastDev.Web.rar
--------------------------个人签名的分割线--------------------------------------
我的个人综合博客:http://www.xiaosonl.com