在C#中,如何使用包装在“C”中的匿名类型项访问词典;“对象”;类型
在C#中,我正在读取类型为在C#中,如何使用包装在“C”中的匿名类型项访问词典;“对象”;类型,c#,C#,在C#中,我正在读取类型为IDictionary的属性Config。我无法访问对象元素中的信息。它应该是一个JSON字符串,但是它被包装为object 在VisualStudio的即时窗口中,键入Config输出: Count = 1 [0]: {[items, Count = 3]} 深入到项目: var configItemsElement = Config["items"] 在即时窗口输出中键入configItemsElement: Count = 3 [0]: {[
IDictionary
的属性Config
。我无法访问对象
元素中的信息。它应该是一个JSON字符串,但是它被包装为object
在VisualStudio的即时窗口中,键入Config
输出:
Count = 1
[0]: {[items, Count = 3]}
深入到项目:
var configItemsElement = Config["items"]
在即时窗口输出中键入configItemsElement
:
Count = 3
[0]: {[1, {{ value = SeoChoiceInherit, sortOrder = 1 }}]}
[1]: {[2, {{ value = SeoChoiceYes, sortOrder = 2 }}]}
[2]: {[3, {{ value = SeoChoiceNo, sortOrder = 3 }}]}
并键入configItemsElement.ToString()
返回此类型信息:
System.Collections.Generic.Dictionary`2[System.String,<>f__AnonymousType7`2[System.String,System.Int32]]
导致错误CS0021:无法将带[]的索引应用于“object”类型的表达式
在VisualStudio的“自动”窗口中,configItemsElement
的信息是
configItemsElement
Value: Count = 3
Type: object {System.Collections.Generic.Dictionary<string, <>f__AnonymousType7<string, int>>}
使configItemsElement
动态,并访问.value
,如symap的回答所示,如下所示:
dynamic configItemsElement = Config["Items"];
var myString =configItemsElement.value;
错误结果:
''object' does not contain a definition for 'value''
我理解,因为
configItemsElement
应该包含一个字典。但是,如上所述,访问dictionary元素也不起作用。您可以使用dynamic来访问成员,而无需进行类型检查
using System;
using System.Collections;
using System.Collections.Generic;
namespace ObjectDictionary
{
class Program
{
static void Main(string[] args)
{
IDictionary <string, object> dict= new Dictionary<String, object>();
dict.Add("abc", new {value = "blah", sortOrder = 1});
dynamic a = dict["abc"];
Console.WriteLine(a.value);
Console.WriteLine(a.sortOrder);
}
}
}
将成为
dynamic configItemsElement = Config["Items"];
var myString =configItemsElement.value;
从您的问题来看,数据似乎没有存储为Json。如果您需要它作为json,那么您需要重建json。
您可能会使用json序列化程序
string json = JsonConvert.SerializeObject(configItemsElement, Formatting.Indented);
Console.WriteLine(json);
您可以使用动态链接来访问成员,而无需进行类型检查
using System;
using System.Collections;
using System.Collections.Generic;
namespace ObjectDictionary
{
class Program
{
static void Main(string[] args)
{
IDictionary <string, object> dict= new Dictionary<String, object>();
dict.Add("abc", new {value = "blah", sortOrder = 1});
dynamic a = dict["abc"];
Console.WriteLine(a.value);
Console.WriteLine(a.sortOrder);
}
}
}
将成为
dynamic configItemsElement = Config["Items"];
var myString =configItemsElement.value;
从您的问题来看,数据似乎没有存储为Json。如果您需要它作为json,那么您需要重建json。
您可能会使用json序列化程序
string json = JsonConvert.SerializeObject(configItemsElement, Formatting.Indented);
Console.WriteLine(json);
类型
System.Collections.Generic.Dictionary
表示您有一个字典,其中键是字符串,值是字符串。由于匿名类型没有名称(无论如何,从C#的角度来看,正如您可以看到的那样,它们在编译的代码中得到了一个生成的名称),因此没有可用于将值强制转换到的类型
您的问题发生在从JSON解析配置时。匿名类型通常只应在单个方法内部使用。如果它们泄漏为对象
引用,您就会遇到问题。如果可能,生成这些配置元素的代码应该固定为使用命名类型
但是,如果不可能,您唯一的退路就是强制转换值。类型
System.Collections.Generic.Dictionary
意味着您有一个字典,其中键是字符串,值是字符串。由于匿名类型没有名称(无论如何,从C#的角度来看,正如您可以看到的那样,它们在编译的代码中得到了一个生成的名称),因此没有可用于将值强制转换到的类型
您的问题发生在从JSON解析配置时。匿名类型通常只应在单个方法内部使用。如果它们泄漏为对象
引用,您就会遇到问题。如果可能,生成这些配置元素的代码应该固定为使用命名类型
然而,如果这不可能,你唯一的退路就是抛出价值观。我回答我自己的问题,因为我收到的宝贵意见为我指明了正确的方向,但没有给我一个有效的解决方案。我是Stackoverflow的新手,所以如果有什么我应该了解的,请告诉我 此外,尽管我找到了一个有效的解决方案,但我不理解@symaps和@shf301的建议在这种情况下为什么不起作用。这就是为什么我感谢进一步的投入 我最终实现这一目标的方法是:
- 为匿名类型声明我自己的类型
- 将
转换为IEnumerableconfigItemsElement
- 在
configItemsElement
- 使用反射获取每个字典项的“内部项”
- 将“内部项”(匿名类型)强制转换为动态
- 并使用反射访问“内部项”的两个属性(
和value
)以将它们添加到新列表中sortOrder
...
public class InnerItemType
{
public int sortOrder { get; set; }
public string value { get; set; }
}
....
List<InnerItemType> listOptions = new List<InnerItemType>();
var configItemsElement = Config["items"] as IEnumerable;
foreach (var item in configItemsElement)
{
dynamic innerItem = item.GetType().GetProperties()[1].GetValue(item);
listOptions.Add(new InnerItemType() {
value = innerItem.GetType().GetProperties()[0].GetValue(innerItem),
sortOrder = innerItem.GetType().GetProperties()[1].GetValue(innerItem)
});
}
...
但是,如果我尝试通过使用如下属性名的动态类型访问innerItem:
foreach (dynamic item in configItemsElement)
{
dynamic innerItem = item.Value;
我收到一个错误“'System.ValueType'不包含'Value'的定义”
同样,如果我尝试直接访问innerItem.value
和innerItem.sortOrder
而不进行反射,如下所示:
foreach (var item in configItemsElement)
{
dynamic innerItem = item.GetType().GetProperties()[1].GetValue(item);
listOptions.Add(new InnerItemType() {
value = innerItem.value,
sortOrder = innerItem.sortOrder
});
给出了相同的错误
我是否误解了
dynamic
的作品?因此,尽管我找到了一个有效的解决方案,但我希望能够充分理解潜在的问题,并感谢进一步的解释。谢谢大家! 我回答了自己的问题,因为我收到的宝贵意见为我指明了正确的方向,但没有给我一个有效的解决方案。我是Stackoverflow的新手,所以如果有什么我应该了解的,请告诉我
此外,尽管我找到了一个有效的解决方案,但我不理解@symaps和@shf301的建议在这种情况下为什么不起作用。这就是为什么我感谢进一步的投入
我最终实现这一目标的方法是:
- 为匿名类型声明我自己的类型
- 将
转换为IEnumerableconfigItemsElement
- 在
configItemsElement
- 使用反射获取每个字典项的“内部项”
- 将“内部项”(匿名类型)强制转换为动态
- 并使用反射访问“内部项”的两个属性(
和value
)以将它们添加到新列表中sortOrder
...
public class InnerItemType
{
public int sortOrder { get; set; }
public string value { get; set; }
}
....
List<InnerItemType> listOptions = new List<InnerItemType>();
var configItemsElement = Config["items"] as IEnumerable;
foreach (var item in configItemsElement)
{
dynamic innerItem = item.GetType().GetProperties()[1].GetValue(item);
listOptions.Add(new InnerItemType() {
value = innerItem.GetType().GetProperties()[0].GetValue(innerItem),
sortOrder = innerItem.GetType().GetProperties()[1].GetValue(innerItem)
});
}
...
但是,如果我尝试通过使用如下属性名的动态类型访问innerItem:
foreach (dynamic item in configItemsElement)
{
dynamic innerItem = item.Value;
我收到一个错误,“'System.ValueType'不包含'