在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)
然后是测试用例, 不太容易理解, 见谅:
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",
};
![]()
![]()
控件#region 控件
![]()
![]()
CheckBox CheckBoxControl = new CheckBox()
{ ID = "_CheckBoxControl" };
![]()
ListBox ListBoxControl = new ListBox()
{ ID = "_ListBoxControl" };
ListBoxControl.Items.Add(new ListItem("一", "0"));
ListBoxControl.Items.Add(new ListItem("二", "1"));
![]()
DropDownList DropDownListControl = new DropDownList()
{ ID = "_DropDownListControl" };
DropDownListControl.Items.Add(new ListItem("一", "0"));
DropDownListControl.Items.Add(new ListItem("二", "1"));
![]()
Label LabelControl = new Label()
{ ID = "_LabelControl" };
![]()
TextBox TextBoxControl = new TextBox()
{ ID = "_TextBoxControl" };
![]()
Custom CustomControl = new Custom()
{ ID = "_CustomControl" };
![]()
Control container = new Control();
container.Controls.Add(CheckBoxControl);
container.Controls.Add(ListBoxControl);
![]()
container.Controls.Add(new TextBox()
{ ID = "txt" });
container.Controls.Add(LabelControl);
container.Controls.Add(CustomControl);
![]()
![]()
Panel tempPanel = new Panel()
{ ID = "_tempPanel" };
tempPanel.Controls.Add(TextBoxControl);
![]()
tempPanel.Controls.Add(new TextBox()
{ ID = "ttt" });
tempPanel.Controls.Add(DropDownListControl);
container.Controls.Add(tempPanel);
![]()
#endregion
![]()
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)
测试用例:
[TestMethod]
public void ControlsToHashAndHashToControlsTest()
![]()
{
![]()
测试数据准备#region 测试数据准备
![]()
Control container = new Control();
![]()
![]()
Label c_UserID = new Label()
{ ID = "c_UserID" };
![]()
TextBox c_UserName = new TextBox()
{ ID = "c_UserName" };
![]()
Control otherInfo = new Control();
![]()
DropDownList c_Age = new DropDownList()
{ ID = "c_Age" };
c_Age.Items.Add(new ListItem("1"));
![]()
DropDownList c_IsUsed = new DropDownList()
{ ID = "c_IsUsed" };
c_IsUsed.Items.Add(new ListItem("True"));
otherInfo.Controls.Add(c_Age, c_IsUsed);
![]()
![]()
RadioButtonList c_RoleID = new RadioButtonList()
{ ID = "c_RoleID" };
c_RoleID.Items.Add(new ListItem("2"));
![]()
container.Controls.Add(c_UserID, c_UserName, otherInfo, c_RoleID);
![]()
#endregion
![]()
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