C# - 动态添加对象(添加动态 属性 名称)
C# - Adding objects dynamically (adding dynamic property names)
我正在尝试创建一些动态 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 中获取的信息构建连接字符串),因此我不知道'知道我需要得到什么数据。这可能是 DB table
的示例
TABLE 促销
- ID: 整数,
- 产品:nvarchar(100),
- 天数:整数,
- 数量:bigint
这可能是另一个例子:
TABLE Foobar
- Id: 整数,
- 天数:整数
- 数量:bigint
- Product_Id: 整数
- Department_Id: 整数
如你所见,我不知道数据库是什么样的(这是 100% 匿名的,因此它需要 100% 动态),我想要 return 的数据应该是这样的结构良好的 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
s,但似乎无法使它工作,因为我无法执行此问题顶部所示的内容 (I不知道属性的名称)。有没有办法让我说这样的话:
var obj = new ExpandoObject();
var propName = "Product";
var obj.propName = "Pie"
Console.WriteLine("Let's print!: " + obj.Product);
//OUTPUT
Let's print!: Pie
有没有人有可能解决这种情况的解决方案,og 简单的结构指导?
与其创建 ExpandoObject
或其他动态类型,不如创建一个 List<Dictionary<string, object>>
,其中每个 Dictionary<string, object>
包含您要序列化的 name/value 对。然后使用 Json.NET (or 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}]
正如您在此处看到的 ExpandoObject Class,ExpandoObject
正在实施 IDictionary<string, object>
,因此您可以像
这样使用该事实
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);
第一部分,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
的静态类型对象。在博客中他们特意喊出了
I didn’t write ExpandoObject contact = new ExpandoObject(), because if I did contact would be a statically-typed object of the ExpandoObject type. And of course, statically-typed variables cannot add members at run time. So I used the new dynamic keyword instead of a type declaration, and since ExpandoObject supports dynamic operations, the code works
因此,如果您重写代码以使用 dynamic obj
,并将动态属性添加为属性,它应该可以工作!
但是对于您的特定用例,您最好按照@dbc
上面的建议使用字典
dynamic obj = new ExpandoObject();
obj.Product= "Pie"
Console.WriteLine("Let's print!: " + obj.Product);
//OUTPUT
Let's print!: Pie
使用 dynamic
,然后转换为 IDictionary<string, object>
以循环访问您的属性:
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);
}
我做了一个fiddle:https://dotnetfiddle.net/yFLy2u
现在这是您问题的解决方案...@dbc 等其他答案可能更适合该问题(这不是问题,真的)
在我写答案的时候,我看到你已经得到了正确的答案。您可以使用 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));
我正在尝试创建一些动态 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 中获取的信息构建连接字符串),因此我不知道'知道我需要得到什么数据。这可能是 DB table
的示例TABLE 促销
- ID: 整数,
- 产品:nvarchar(100),
- 天数:整数,
- 数量:bigint
这可能是另一个例子:
TABLE Foobar
- Id: 整数,
- 天数:整数
- 数量:bigint
- Product_Id: 整数
- Department_Id: 整数
如你所见,我不知道数据库是什么样的(这是 100% 匿名的,因此它需要 100% 动态),我想要 return 的数据应该是这样的结构良好的 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
s,但似乎无法使它工作,因为我无法执行此问题顶部所示的内容 (I不知道属性的名称)。有没有办法让我说这样的话:
var obj = new ExpandoObject();
var propName = "Product";
var obj.propName = "Pie"
Console.WriteLine("Let's print!: " + obj.Product);
//OUTPUT
Let's print!: Pie
有没有人有可能解决这种情况的解决方案,og 简单的结构指导?
与其创建 ExpandoObject
或其他动态类型,不如创建一个 List<Dictionary<string, object>>
,其中每个 Dictionary<string, object>
包含您要序列化的 name/value 对。然后使用 Json.NET (or 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}]
正如您在此处看到的 ExpandoObject Class,ExpandoObject
正在实施 IDictionary<string, object>
,因此您可以像
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);
第一部分,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
的静态类型对象。在博客中他们特意喊出了
I didn’t write ExpandoObject contact = new ExpandoObject(), because if I did contact would be a statically-typed object of the ExpandoObject type. And of course, statically-typed variables cannot add members at run time. So I used the new dynamic keyword instead of a type declaration, and since ExpandoObject supports dynamic operations, the code works
因此,如果您重写代码以使用 dynamic obj
,并将动态属性添加为属性,它应该可以工作!
但是对于您的特定用例,您最好按照@dbc
上面的建议使用字典dynamic obj = new ExpandoObject();
obj.Product= "Pie"
Console.WriteLine("Let's print!: " + obj.Product);
//OUTPUT
Let's print!: Pie
使用 dynamic
,然后转换为 IDictionary<string, object>
以循环访问您的属性:
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);
}
我做了一个fiddle:https://dotnetfiddle.net/yFLy2u
现在这是您问题的解决方案...@dbc 等其他答案可能更适合该问题(这不是问题,真的)
在我写答案的时候,我看到你已经得到了正确的答案。您可以使用 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));