【问题标题】:Dynamically setting property inside own class在自己的类中动态设置属性
【发布时间】:2013-02-18 13:07:59
【问题描述】:

我想我已经很接近解决这个问题了,但我已经有一段时间没有取得进展了,除了四处打听之外别无选择。

我有一个带有大量图形属性的GraphicsSettings 类。这些属性有一个带有属性名称的占位符值,我将其用于比较循环。

比较循环是类内部的一个函数,位于图形属性数组和遍历外部文本文件中行的Stringreader 之间。

当循环发现图形属性的值与行中的一部分内容匹配时,我想将行的整个值设置到图形属性中。

但问题是,我不知道如何从类中调用属性设置器而不专门输入它的名称,因为它是一个循环,所以我不能这样做。

我尝试过使用:

this.GetType().GetProperty(key).SetValue(this,line, null);

其中“key”是属性名称,“line”是行值。据我了解,这在从外部调用类对象来设置值时应该可以正常工作,但似乎完全反对使用这种方法从内部调用类。

我得到的只是一个 TargetInvocationException was unhandled 错误。不太令人惊讶,但我不知道如何解决这个问题。

所以我想归根结底是:如何从属性所在的同一个类中通过使用字符串访问属性?

【问题讨论】:

  • 我认为您需要发布一些代码,包括引发异常的行,因为这应该没有问题。
  • 另外,TargetInvocationException 可能具有相当的欺骗性。请务必检查所有嵌套的 InnerException,因为它们很可能会让您更好地了解真正的根本原因。
  • 假设key 实际上是属性名称(区分大小写)并且该行没有破坏任何类型边界(例如将null 设置为int)。

标签: c# class dynamic properties


【解决方案1】:

如果属性不是公共的,您可能需要使用绑定标志,因为GetProperty 方法不知道您是从目标类中调用它。 C# 的可访问性规则适用于静态代码文本,此处不适用。

PropertyInfo prop = this.GetType().GetProperty(key, BindingFlags.Instance | 
                                                    BindingFlags.NonPublic);
prop.SetValue(this, "data", null);

请注意,查找属性区分大小写。因此,您可能还需要包含 IgnoreCase 标志。

PropertyInfo prop = this.GetType().GetProperty(key, BindingFlags.Instance |
                                                    BindingFlags.NonPublic |
                                                    BindingFlags.IgnoreCase);
prop.SetValue(this, "data", null);

如果您的属性是静态的,则应指定 BindingFlags.Static 标志而不是 BindingFlags.Instance 标志。您还可以将两者结合起来,也可以将 BindingFlags.NonPublic | BindingFlags.Public 组合起来用于混合情况。


还要注意类型必须匹配。 C# 的隐式类型转换在这里不起作用。所以总是为SetValue的值参数(第二个参数)提供正确的类型。例如

string input = "123";
prop.SetValue(this, Int32.Parse(input), null);

int i = 77;
prop.SetValue(this, (double)i, null);

如果属性是double 类型,也将int 显式转换为double


Chris Kerekes 建议将 prop.MemberTypeConvert.ChangeType 结合使用以获得完全动态的方法,如果您有不同类型的属性(至少对于最常见的类型),该方法将有效。

prop.SetValue(this, Convert.ChangeType(line, prop.MemberType), null);

【讨论】:

  • 很好的答案,虽然我可能会建议通过 prop.SetValue(this, Convert.ChangeType(line, prop.MemberType), null); 转换 clr 类型
  • 像魅力一样工作 ;) 非常感谢。
  • @Chris Kerekes:是的,您的解决方案允许采用非常动态的方法。
猜你喜欢
  • 2021-06-17
  • 2012-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-04
  • 1970-01-01
  • 2013-02-19
相关资源
最近更新 更多