使用反射在运行时获取控件属性
.NET 中轻松访问控件属性
引言
Control
类是 .NET Framework 提供的一个非常重要的类,它位于 System.Componentmodel.Component
命名空间下。无论您使用的是Windows、Web 还是移动应用程序,都会用到这个类。
我们都知道,在设计时和编译时很容易访问所有控件的属性。但是,在运行时获取某些控件的属性会涉及到一些复杂性。
从 Control
类派生出了不同类型的控件,例如 WebControls
、MobileControls
,它们具有一些共同的属性和属性类型。在 Control
类中,有几个控件共享字符串属性 "Text
",并且大多数窗体控件以基本相同的方式使用此属性。它用于获取和设置用户输入的数据。还有其他一些通用的属性和属性类型被各种控件使用。
在本文中,我们将讨论如何通过编程方式使用反射,仅用一行代码在运行时访问重要的控件属性,例如 "Text" 属性,从而减少代码行数并提高可读性(这里我们只讨论单个属性 "Text")。
使用此技术,您可以将逻辑扩展到运行时任何控件的任何数量的属性,而不管控件的类型如何。通过这样做,您还可以使用户能够动态地获取或设置控件的任何属性值。
使用 System.Reflection
反射是在运行时读取元数据的能力。使用反射,可以动态地发现类型的成员(方法、属性和事件)并调用它们。在 .NET Framework 中,编译器在编译期间会生成元数据,并将元数据(以二进制格式)存储在程序集和模块中。
System.Type
类是反射中的主要类。它表示类型声明(类类型、接口类型、数组类型、值类型和枚举类型)。System.Type
也是访问元数据的主要入口点。它提供了获取类型声明信息的方法,例如构造函数、属性、方法和事件。Propertyinfo
类是 System.Type
的一个对象,此方法返回一个 PropertyInfo
类型对象的数组,该类属于 System.Reflection
命名空间。
示例
在下面的 Web 窗体中,我们将使用一些标准控件并在设计页面时设置所需的属性,在本例中是一个 Label、一个 Textbox 和一个 Button。我们将编写代码,以便能够访问运行时属性。
protected void Button1_Click1(object sender, EventArgs e)
{
DisplyDetails(this);
}
In the above code, we invoke the DisplyDetails() method passing the object of control class by "this" reference object in Button Click event handler.
private void DisplyDetails(Control control)
{
foreach (Control controls in this.form1.Controls)
{
string controlId = controls.ID;
Response.Write(controlId);
Response.Write("<br>");
Type controlType = controls.GetType();
PropertyInfo[] properties = controlType.GetProperties();
foreach (PropertyInfo controlProperty in properties)
{
if (controlProperty.Name == "Text" &&
controlProperty.PropertyType == typeof(String))
{
string propertyValue = GetPropertyValue(controlProperty.Name, controls);
Response.Write(propertyValue);
Response.Write("<br><br>");
}
}
}
}
在上面的代码中,我们有一个 ControlCollection
对象,它表示 UI 层次结构中特定服务器控件的子控件。使用 for each 循环,我们检查 ASP.NET 控件的 Controlcollection
对象并获取 ID 属性。我们获取控件对象的 Type,并使用该 Type 获取一个 PropertyInfo
对象数组。每个 PropertyInfo
对象都包含有关我们的控件对象属性的信息,以及从控件对象获取和设置值的能力。
通过调用 GetProperties
方法,我们获得一个 PropertyInfo
对象数组。PropertyInfo
类为数组中的每个对象提供名称和属性类型。我们将遍历 PropertyInfo
数组,查找名为 "Text" 的 String
属性。如果控件具有该属性,我们将调用 GetPropertyValue()
方法,并将属性名称和控件类对象作为两个参数传递。获取属性值的代码如下所示。
private string GetPropertyValue(string pName, Control control)
{
Type type = control.GetType();
string propertyName = pName;
BindingFlags flags = BindingFlags.GetProperty;
Binder binder = null;
object[] args = null;
object value = type.InvokeMember(
propertyName,
flags,
binder,
control,
args
);
return value.ToString();
}
在上面的代码中,我们有属性名称和控件类对象,我们将使用它们来获取对象的类型。类型对象具有 InvokeMethod()
方法,可用于调用类型对象所描述类的成员。InvokeMember()
有重载,上面的版本接受五个参数,如下所示。
PropertyName
:PropertyName
是您希望调用的方法或属性的名称。
Flags
:是 BindingFlags
的位掩码,用于指定如何进行对象搜索。在这种情况下,我们将使用 GetProperty
标志。这些是动态调用方法的标准标志。
Binder
:Binder 用于辅助类型转换。通过传递 null,我们将指定我们想要默认的 binder。
Control
:Control
是运行时将尝试在其上调用成员的对象,因此我们传递对所选控件的引用。
Args
:一个要传递给我们要调用的成员的参数数组。由于获取属性不需要任何参数,因此我们可以传递 null 值。
调用此方法的结果被分配给局部变量 "value",然后该值作为字符串返回到 DispalyDetails()
方法,在那里显示。
此代码适用于所有标准的 .NET 控件以及第三方控件,前提是该控件已从控件类派生并且包含所需的属性。