【问题标题】:Add properties to class dynamically C#为类动态添加属性 C#
【发布时间】:2013-05-16 19:09:34
【问题描述】:

我想动态地向一个类添加属性并为它们设置值。有人可以为我指出一些教程或文章的正确方向,或者更好地提供一个示例。

我有一个在 foreach 循环中调用的基类。在这个类中,我需要添加多达 30 个属性并为它们设置值。

这是调用类的方法。

foreach (Class name in this.list)
{
    ClassBeingCalled class = new ClassBeingCalled (name);
    class.Populate();
    this.newlist.Add(class);
}

现在在被调用的类中,我需要动态创建大约 30 个属性,这些属性将在该类的“Populate”方法中设置。

就这样……

 foreach (PropertyToAssign count2 in listofproperties)
 {
     string name = "_nameofproperty" + count2.name
     base.GetType().GetField(name, BindingFlags.NonPublic |
                          BindingFlags.Instance).SetValue(this, count2);
 }

【问题讨论】:

  • 只使用“listofproperties”而不是尝试创建动态属性有什么问题?如果它必须是动态的,请查看msdn.microsoft.com/en-us/library/vstudio/dd264741.aspx
  • 这些东西存在为属性吗?即您是否尝试创建 new 属性?还是为现有属性赋值?
  • 尝试创建新属性。目前,它有一组我想更改为动态的属性。例如,它有 10 个属性。但是,如果将新属性添加到属性列表中,则会在此处出错:base.GetType().GetField(name, BindingFlags.NonPublic | BindingFlags.Instance).SetValue(this, count2);因为有比定义更多的属性。
  • 我认为您可能应该考虑只使用带有索引器的内部字典,因此您可以访问您的属性,例如 myObject["PropertyName"](您可以使用 ExpandObject 有效地实现相同的目标)。跨度>
  • 顺便说一句,标题中写着“属性”,但在填充方法中它反映了“字段”

标签: c#


【解决方案1】:

有几种方法可以解决这个问题。

a) 您可以使用反射在运行时根据您的需要生成一个类。您始终可以从包含 Populate 的基类派生这个生成的类,但我认为没有必要。

b) 如果您使用 C# 4.0+,您可以使用ExpandoObject,它允许您根据需要设置所需的任何属性。请注意,这些 不是 作为属性本身添加的,因为它使用了所有基于运行时的 DLR。根据您的需要,这可能没问题;这与方法 c 几乎相同,但使用的是 DLR。

c) 您可以使用支持字典并使用indexer,如下所示:

private Dictionary<string, object> _internalData = new Dictionary<string, object>();

public T this[string propName]
{
    get {
        return _internalData[propName];
    }
    set {
        _internalData[propName] = value;
    }
}

通过使用方法 3,您实际上是基于 strings 建立索引,这可能更适合您的要求...您可以按照以下方式进行操作:

foreach (PropertyToAssign count2 in listofproperties)
{
    string name = "_nameofproperty" + count2.name;
    this[name] = count2.value;
}

在一天结束时,最好解释一下您要解决的问题,因为可能有更好的方法来完全解决它。

【讨论】:

  • 我以为我在上面做了:-(。你还需要什么其他信息?
  • 您建议了在类上设置属性的现有解决方案,并告诉我们您需要添加属性。实际上,您可能应该在这里查看选项 c(其他人在此问题中也建议过),而不是设置属性,只需在内部字典上设置值。
  • 如何定义字典中的属性类型?
  • 好吧,你不知道。你使用object,这样你就可以把任何东西放在那里。如果您只有 1 种数据类型,您可以随时将 object 更改为 string,或任何该类型。
  • 您好 Rudi,我收到以下错误:无法使用 [] 对类型为“BusinessLogic.InvoiceBaseUIBindable”的表达式应用索引添加此内容后 - this[name] = count2.value;
【解决方案2】:

无法动态地向已编译的类添加动态属性。您只能在使用 Reflection.Emit 动态构建类本身时向类添加动态属性

您的其他选择可能是使用字典或ExpandoObject(实际上是字典)。但对于此选项,您无法使用反射访问动态属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-13
    • 1970-01-01
    • 1970-01-01
    • 2015-12-12
    • 2019-04-28
    • 1970-01-01
    相关资源
    最近更新 更多