【问题标题】:C# - Adding objects dynamically (adding dynamic property names)C# - 动态添加对象(添加动态属性名称)
【发布时间】:2015-12-12 17:11:24
【问题描述】:

我正在尝试创建一些动态的ExpandoObject。我遇到了某个问题。

由于我不知道我的对象中这些不同属性的名称应该是什么,所以我不能这样做:

var list = new ArrayList();

var obj = new ExpandoObject();
obj.ID = 1,
obj.Product = "Pie",
obj.Days = 1,
obj.QTY = 65

list.Add(obj);

让我解释一下我的情况:我希望从随机数据库中获取数据(我不知道是哪个,但是根据从 UI 获得的信息构建连接字符串),因此我不知道我的数据是什么需要得到。这可能是一个数据库表的例子

餐桌销售

  • ID:整数,
  • 产品:nvarchar(100),
  • 天数:整数,
  • 数量:大整数

这可能是另一个例子:

TABLE Foobar

  • ID:整数,
  • 天数:整数
  • 数量:大整数
  • Product_Id:int
  • Department_Id:int

如您所见,我不知道数据库是什么样的(这是 100% 匿名的,因此它需要是 100% 动态的),并且我想要返回的数据应该看起来像一个构造良好的 JSON,例如所以:

[
  {
    "ID": 1,
    "Product": "Pie"
    "Days": 1,
    "QTY": 65
  },
  {
    "ID": 2,
    "Product": "Melons"
    "Days": 5,
    "QTY": 12
  }
]

或者,用另一个例子:

[
  {
    "ID": 1,
    "Days": 2,
    "QTY": 56,
    "Product_Id": 5,
    "Department_Id": 2
  }
  {
    "ID": 2,
    "Days": 6,
    "QTY": 12,
    "Product_Id": 2,
    "Department_Id": 5
  }
]

我已经尝试使用这些 ExpandoObjects,但似乎无法使其工作,因为我无法执行此问题顶部所示的操作(我不知道名称的属性)。有没有办法让我说:

var obj = new ExpandoObject();
var propName = "Product";

var obj.propName = "Pie"

Console.WriteLine("Let's print!: " + obj.Product);

//OUTPUT
Let's print!: Pie

有没有人有可能解决这种情况的解决方案,例如对结构的简单指导?

【问题讨论】:

  • 您使用什么语言?您标记了 C#,但您的一些代码是 Java(即 System.out.printline) - .NET 没有这个。
  • 我没有复制粘贴任何代码。我只是不记得它在 C# 中叫什么。这是纯 C#,仅此而已。我很抱歉。会更正
  • 只需创建一个List<Dictionary<string, object>>。如果您使用Json.NET 将其序列化为 JSON,您将得到您想要的。
  • @GSerg 其中ExpandoObject 是:)

标签: c# json dynamic structure expandoobject


【解决方案1】:

在我写答案的时候,我看到你已经得到了正确的答案。您可以使用Dictionary<string, onject> 甚至Tuple

但根据您最初的问题,您想动态添加属性。为此,您可以使用ExpandoObject 参考其他答案。这与具有与您的代码类似的类的相同解决方案(使用ExpandoObject 动态添加属性)。

//example classes
public class DictKey
{
    public string DisplayName { get; set; }
    public DictKey(string name) { DisplayName = name; }
}

public class DictValue
{
    public int ColumnIndex { get; set; }
    public DictValue(int idx) { ColumnIndex = idx; }
}

//utility method
public static IDictionary<string, object> GetExpando(KeyValuePair<DictKey, List<DictValue>> dictPair)
{
    IDictionary<string, object> dynamicObject = new ExpandoObject();
    dynamicObject["Station"] = dictPair.Key.DisplayName;
    foreach (var item in dictPair.Value)
    {
        dynamicObject["Month" + (item.ColumnIndex + 1)] = item;
    }
    return dynamicObject;
}

Ans 用法示例:

var dictionaryByMonth = new Dictionary<DictKey, List<DictValue>>();
dictionaryByMonth.Add(new DictKey("Set1"), new List<DictValue> { new DictValue(0), new DictValue(2), new DictValue(4), new DictValue(6), new DictValue(8) });
dictionaryByMonth.Add(new DictKey("Set2"), new List<DictValue> { new DictValue(1), new DictValue(2), new DictValue(5), new DictValue(6), new DictValue(11) });

var rowsByMonth = dictionaryByMonth.Select(item => GetExpando(item));

【讨论】:

    【解决方案2】:

    使用dynamic,然后转换为IDictionary&lt;string, object&gt; 以循环访问您的属性:

    dynamic obj = new ExpandoObject();
    obj.Product = "Pie";
    obj.Quantity = 2;
    
    // Loop through all added properties       
    foreach(var prop in (IDictionary<string, object>)obj)
    {
      Console.WriteLine(prop.Key + " : " + prop.Value);
    }
    

    我做了一个小提琴:https://dotnetfiddle.net/yFLy2u

    现在这是您问题的解决方案......像@dbc 之类的其他答案可能更适合这个问题(这不是问题,真的)

    【讨论】:

      【解决方案3】:

      第一部分,仔细阅读 C# 团队的this blog post

      让我们看看你的代码

      var obj = new ExpandoObject();
      var propName = "Product";
      
      var obj.propName = "Pie"
      
      Console.WriteLine("Let's print!: " + obj.Product);
      
      //OUTPUT
      Let's print!: Pie
      

      在您的代码中,您使用的是var obj = new ExpandoObject();,因此您正在创建一个ExpandableObject 类型的静态类型对象。他们在博客中特别提到了

      我没有写 ExpandoObject contact = new ExpandoObject(),因为如果我写了,contact 将是 ExpandoObject 类型的静态类型对象。当然,静态类型变量不能添加运行时的成员。所以我使用了新的动态关键字而不是类型声明,并且由于 ExpandoObject 支持动态操作,所以代码可以工作

      因此,如果您重写代码以使用dynamic obj,并将动态属性添加为属性,它应该可以工作!

      但对于您的特定用例,您最好使用上面@dbc 建议的字典

      dynamic obj = new ExpandoObject();
      obj.Product= "Pie"    
      Console.WriteLine("Let's print!: " + obj.Product);    
      //OUTPUT
      Let's print!: Pie
      

      【讨论】:

      • 他和你的代码都不起作用。他们甚至不会编译。当您通过删除不需要的var 并添加缺少的; 来编译它们时,您会看到它没有按照您的预期执行并抛出异常而不是打印“Pie”,因为此代码添加了属性propNameobj,而不是财产Product
      • c**p,我注意到只有静态类型是问题所在。将编辑我的答案以修复它们。我目前无法访问 Visual Studio,来 SO 是为了别的,看到了这个!
      【解决方案4】:

      您可以创建List&lt;Dictionary&lt;string, object&gt;&gt;,而不是创建ExpandoObject 或其他动态类型,其中每个Dictionary&lt;string, object&gt; 都包含您要序列化的名称/值对。然后使用Json.NET(或JavaScriptSerializer,虽然不太灵活)序列化为JSON:

              var list = new List<Dictionary<string, object>>();
      
              // Build a dictionary entry using a dictionary initializer: https://msdn.microsoft.com/en-us/library/bb531208.aspx
              list.Add(new Dictionary<string, object> { { "ID", 1 }, {"Product", "Pie"}, {"Days", 1}, {"QTY", 65} });
      
              // Build a dictionary entry incrementally
              // See https://msdn.microsoft.com/en-us/library/xfhwa508%28v=vs.110%29.aspx
              var dict = new Dictionary<string, object>();
              dict["ID"] = 2;
              dict["Product"] = "Melons";
              dict["Days"] = 5;
              dict["QTY"] = 12;
              list.Add(dict);
      
              Console.WriteLine(JsonConvert.SerializeObject(list, Formatting.Indented));
              Console.WriteLine(new JavaScriptSerializer().Serialize(list));
      

      第一个输出:

      [
        {
          "ID": 1,
          "Product": "Pie",
          "Days": 1,
          "QTY": 65
        },
        {
          "ID": 2,
          "Product": "Melons",
          "Days": 5,
          "QTY": 12
        }
      ]
      

      第二个输出相同,没有缩进:

      [{"ID":1,"Product":"Pie","Days":1,"QTY":65},{"ID":2,"Product":"Melons","Days":5,"QTY":12}]
      

      【讨论】:

      • 在我的情况下不会真正起作用,因为我没有所有可用的值,但我需要遍历它们。你能举个例子吗? var valueList = allRowValuesvar clumn = allClumnNames(正在编辑主要问题)
      • 如果在创建 @Detilium 之后无法 add 数据,字典将毫无用处。
      • @dbc 出于某种原因,我的 Json 看起来像这样:[{\"ID\":1,\"Product\":\"Honning\",\"Days\":1,\"QTY\":65}]
      • @Detilium - 在这个问题的任何地方都没有提到邮递员,所以我不确定那是什么 - 你的问题有Console.WriteLine()。但是,如果您以某种方式发布此内容,那么您可能会以某种方式成为double-serializing your JSON
      • @dbc 我做了双重序列化。现在一切正常。感谢您花时间在这里。我真的很感激
      【解决方案5】:

      正如你在这里看到的ExpandoObject ClassExpandoObject 正在实现IDictionary&lt;string, object&gt;,所以你可以像这样使用这个事实

      IDictionary<string, object> obj = new ExpandoObject();
      var propName = "Product";
      obj[propName] = "Pie"
      Console.WriteLine("Let's print!: " + obj[propName]);
      // Verify it's working
      Console.WriteLine("Let's print again!: " + ((dynamic)obj).Product);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-09-27
        • 2012-01-12
        • 2014-05-29
        • 2011-10-05
        • 2017-10-14
        • 1970-01-01
        • 2016-07-31
        相关资源
        最近更新 更多