C# – 动态添加对象(添加动态属性名称)

我正在尝试创建一些动态的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:int,
  • 产品:nvarchar(100),
  • 天:int,
  • 数量:bigint

这可能是另一个例子:

表Foobar

  • Id:int,
  • 天:int
  • 数量:bigint
  • 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 } ] 

我已尝试使用这些ExpandoObject ,但似乎无法使其工作,因为我不能做这个问题的顶部说明( 我不知道属性的名称 )。 有没有办法让我这样说:

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

有没有人有解决方案,只需指导一个结构,这可能会解决这种情况?

您可以创建List> ,而不是创建ExpandoObject或其他动态类型,其中每个Dictionary包含要序列化的名称/值对。 然后使用Json.NET (或JavaScriptSerializer序列化为JSON,尽管灵活性较低:

  var list = new List>(); // Build a dictionary entry using a dictionary initializer: https://msdn.microsoft.com/en-us/library/bb531208.aspx list.Add(new Dictionary { { "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(); 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}] 

使用dynamic ,然后强制转换为IDictionary以遍历您的属性:

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

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

现在这是你的问题的解决方案……像@ dbc这样的其他答案可能更适合问题(这不是问题,真的)

正如您在此处看到的ExpandoObject类 , ExpandoObject正在实现IDictionary ,因此您可以像使用这样的事实

 IDictionary 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); 

在我写答案时,我看到你已经得到了正确答案。 您可以使用Dictionary甚至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 GetExpando(KeyValuePair> dictPair) { IDictionary 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>(); dictionaryByMonth.Add(new DictKey("Set1"), new List { new DictValue(0), new DictValue(2), new DictValue(4), new DictValue(6), new DictValue(8) }); dictionaryByMonth.Add(new DictKey("Set2"), new List { new DictValue(1), new DictValue(2), new DictValue(5), new DictValue(6), new DictValue(11) }); var rowsByMonth = dictionaryByMonth.Select(item => GetExpando(item)); 

第一部分,彻底阅读C#团队的这篇博文 。

让我们看看你的代码

 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(),因为如果我确实联系将是ExpandoObject类型的静态类型对象。 当然,静态类型的变量不能在运行时添加成员。 所以我使用了新的dynamic关键字而不是类型声明,因为ExpandoObject支持动态操作,所以代码可以工作

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

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

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