获取类属性名称
时间:2020-03-06 14:54:49 来源:igfitidea点击:
我的Winform应用程序使用数据绑定收集数据。一切看起来都很好,除了我必须使用字符串将属性与textedit链接:
Me.TextEdit4.DataBindings.Add(New System.Windows.Forms.Binding("EditValue", Me.MyClassBindingSource, "MyClassProperty", True))
这可以正常工作,但是如果我更改类的属性名称,则编译器显然不会警告我。
我希望能够通过反射获取属性名称,但是我不知道如何指定所需属性的名称(我只知道如何在类的所有属性之间进行迭代)
任何的想法?
解决方案
具有讽刺意味的是,反射期望我们提供属性名称以获取其信息:)
我们可以创建自定义属性,将其应用于所需的属性。然后,我们将能够简单地获取具有此属性的属性的名称。
使用反射会遇到相同的问题,因为为了在所有类型的属性中找到正确的属性,我们必须知道其名称,对吗?
我们可以反映类型,但不能反映其成员,除非按名称。
如果那是唯一的属性,或者我们确定可以通过索引找到它的顺序,那么通常来说字符串是最安全的选择。
我相信更改名称将导致运行时异常,但不是100%可以肯定,在任何一种情况下这都可能是最好的可能性。
假设没有异常自动发生,我们可以添加一个Debug.Assert来检查该名称的属性是否存在,但同样仅是运行时。
1)指定所需的确切属性名称,并保持该名称不变
2)编写一个涉及该属性名称的测试。
这是我正在谈论的示例:
[AttributeUsage(AttributeTargets.Property)] class TextProperyAttribute: Attribute {} class MyTextBox { [TextPropery] public string Text { get; set;} public int Foo { get; set;} public double Bar { get; set;} } static string GetTextProperty(Type type) { foreach (PropertyInfo info in type.GetProperties()) { if (info.GetCustomAttributes(typeof(TextProperyAttribute), true).Length > 0) { return info.Name; } } return null; } ... Type type = typeof (MyTextBox); string name = GetTextProperty(type); Console.WriteLine(name); // Prints "Text"
如果使用的是C3.0,则有一种方法可以动态获取属性名称,而无需对其进行硬编码。
private string GetPropertyName<TValue>(Expression<Func<BindingSourceType, TValue>> propertySelector) { var memberExpression = propertySelector.Body as MemberExpression; return memberExpression != null ? memberExpression.Member.Name : string.empty; }
其中," BindingSourceType"是数据源对象实例的类名称。
然后,我们可以使用lambda表达式以强类型方式选择要绑定的属性:
this.textBox.DataBindings.Add(GetPropertyName(o => o.MyClassProperty), this.myDataSourceObject, "Text");
这将使我们能够安全地重构代码,而不会停止所有的数据绑定工作。但是就性能而言,使用表达式树与使用反射相同。
先前的代码非常丑陋且未经检查,但是我们可以理解。