Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将类实例转换为字典以进行迭代_C#_Json.net - Fatal编程技术网

C# 将类实例转换为字典以进行迭代

C# 将类实例转换为字典以进行迭代,c#,json.net,C#,Json.net,我想要一个泛型函数将任何类实例转换为dict,这样我就可以以泛型的方式轻松地使用它。在我的例子中,我想将任何实例SSF.Mod转换成一个dict,我可以在此基础上迭代动态生成部分UI 我曾想过使用json.net,但经过快速检查,我发现没有人会要求同样的理由 SSF.Mod类的精简版本: 名称空间SSF { 公共类FileWithHash { 公共字符串私有路径{get;set;} 公共文件WithHash(字符串共享路径,字符串哈希) { PrivatePath=sharedPath;Hash

我想要一个泛型函数将任何类实例转换为dict,这样我就可以以泛型的方式轻松地使用它。在我的例子中,我想将任何实例
SSF.Mod
转换成一个dict,我可以在此基础上迭代动态生成部分UI

我曾想过使用json.net,但经过快速检查,我发现没有人会要求同样的理由

SSF.Mod类的精简版本:

名称空间SSF
{
公共类FileWithHash
{
公共字符串私有路径{get;set;}
公共文件WithHash(字符串共享路径,字符串哈希)
{
PrivatePath=sharedPath;Hash=Hash;
}
}
公共类模块
{
[JsonIgnore]
私人游戏{get;set;}
公共场所残疾人{
获取{…}
}
公共字符串Id{get;set;}
public DirectoryInfo目录{get;set;}
public FileWithHash GroFile{get;set;}
公共文件WithHash缩略图{get;set;}
公共发布的详细信息{get;set;}
公共列表标记{get{
如果(详细信息为空)返回空;
var ret=新列表();
foreach(Details.tags中的var标记){
ret.Add(tag.tag);
}
返回ret;
} }
}
}
将Instance示例缩减为json:

{
  "Disabled": false,
  "Id": "1805661862",
  "Directory": {
    "OriginalPath": "S:\\Steam\\steamapps\\workshop\\content\\564310\\1805661862",
    "FullPath": "S:\\Steam\\steamapps\\workshop\\content\\564310\\1805661862"
  },
  "WorkshopVersion": "WorkshopVersion_01",
  "GroFile": {
    "PrivatePath": "Gro_File/DeepValley.gro",
    "Hash": "B68F60F4C87077DAF59F684B0306963BA6D4B351"
  },
  "Details": {
    "publishedfileid": "1805661862",
    "result": 1,
    "creator": "76561198016985053",
    "creator_app_id": 564380,
    "consumer_app_id": 564310,
    "filename": "",
  }
我想到了类似的事情

Dictionary<string, object> dictOfMod = instanceOfMod.toDict();
foreach(var entry in dictOfMod){
   if (entry is bool) etc...
Dictionary dictOfMod=instanceOfMod.toDict();
foreach(dictOfMod中的var条目){
如果(输入为布尔)等。。。

将实例转换为
字典

Mod mod = new Mod();

var modDictionary = mod.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
         .ToDictionary(
           propertyInfo => propertyInfo.Name,
           propertyInfo => propertyInfo.GetValue(mod));

编辑 以下方法将类型及其完整的声明类型树转换为
字典

评论
字典
的默认
是属性名

集合被转换为
字典
,其中
是项的索引。
这种字典的最后一项是计数,其中
键是
“count”

要确定
词典
是否为集合,请使用返回布尔值的

您可以使用此扩展方法:

Extensions.cs

public static class Extensions
{
  public static Dictionary<string, object> ToDictionary(this object instanceToConvert)
  {
    Dictionary<string, object> resultDictionary = instanceToConvert.GetType()
      .GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
      .Where(propertyInfo => !propertyInfo.GetIndexParameters().Any())
      .ToDictionary(
        propertyInfo => propertyInfo.Name,
        propertyInfo => Extensions.ConvertPropertyToDictionary(propertyInfo, instanceToConvert));
    resultDictionary.Add("IsCollection", false);
    return resultDictionary;
  }

  private static object ConvertPropertyToDictionary(PropertyInfo propertyInfo, object owner)
  {
    Type propertyType = propertyInfo.PropertyType;
    object propertyValue = propertyInfo.GetValue(owner);
    if (propertyValue is Type)
    {
      return propertyValue;
    }

    // If property is a collection don't traverse collection properties but the items instead
    if (!propertyType.Equals(typeof(string)) && typeof(IEnumerable).IsAssignableFrom(propertyType))
    {
      var items = new Dictionary<string, object>();
      var enumerable = propertyInfo.GetValue(owner) as IEnumerable;
      int index = 0;
      foreach (object item in enumerable)
      {
        // If property is a string stop traversal
        if (item.GetType().IsPrimitive || item is string)
        {
          items.Add(index.ToString(), item);
        }
        else if (item is IEnumerable enumerableItem)
        {
          items.Add(index.ToString(), ConvertIEnumerableToDictionary(enumerableItem));
        }
        else
        {
          Dictionary<string, object> dictionary = item.ToDictionary();
          items.Add(index.ToString(), dictionary);
        }

        index++;
      }

      items.Add("IsCollection", true);
      items.Add("Count", index);
      return items;
    }

    // If property is a string stop traversal
    if (propertyType.IsPrimitive || propertyType.Equals(typeof(string)))
    {
      return propertyValue;
    }

    PropertyInfo[] properties =
      propertyType.GetProperties(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
    if (properties.Any())
    {
      Dictionary<string, object> resultDictionary = properties.ToDictionary(
        subtypePropertyInfo => subtypePropertyInfo.Name,
        subtypePropertyInfo => propertyValue == null
          ? null
          : (object) Extensions.ConvertPropertyToDictionary(subtypePropertyInfo, propertyValue));
      resultDictionary.Add("IsCollection", false);
      return resultDictionary;
    }

    return propertyValue;
  }

  private static Dictionary<string, object> ConvertIEnumerableToDictionary(IEnumerable enumerable)
  {
    var items = new Dictionary<string, object>();
    int index = 0;
    foreach (object item in enumerable)
    {
      // If property is a string stop traversal
      if (item.GetType().IsPrimitive || item is string)
      {
        items.Add(index.ToString(), item);
      }
      else
      {
        Dictionary<string, object> dictionary = item.ToDictionary();
        items.Add(index.ToString(), dictionary);
      }

      index++;
    }

    items.Add("IsCollection", true);
    items.Add("Count", index);
    return items;
  }
}
公共静态类扩展
{
公共静态字典ToDictionary(此对象instanceToConvert)
{
Dictionary resultDictionary=instanceToConvert.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
.Where(propertyInfo=>!propertyInfo.GetIndexParameters().Any())
.ToDictionary(
propertyInfo=>propertyInfo.Name,
propertyInfo=>Extensions.ConvertPropertyToDictionary(propertyInfo,instanceToConvert));
resultDictionary.Add(“IsCollection”,false);
返回结果字典;
}
私有静态对象ConvertPropertyToDictionary(PropertyInfo PropertyInfo,对象所有者)
{
类型propertyType=propertyInfo.propertyType;
对象propertyValue=propertyInfo.GetValue(所有者);
if(propertyValue为类型)
{
返回属性值;
}
//如果属性是集合,则不遍历集合属性,而是遍历项
如果(!propertyType.Equals(typeof(string))&&typeof(IEnumerable).IsAssignableFrom(propertyType))
{
var items=newdictionary();
var enumerable=propertyInfo.GetValue(所有者)作为IEnumerable;
int指数=0;
foreach(可枚举中的对象项)
{
//如果属性是字符串,则停止遍历
if(item.GetType().IsPrimitive | | item为字符串)
{
添加(index.ToString(),item);
}
else if(项为IEnumerable enumerableItem)
{
Add(index.ToString(),convertieneumerabletodictionary(enumerableItem));
}
其他的
{
Dictionary Dictionary=item.ToDictionary();
items.Add(index.ToString(),dictionary);
}
索引++;
}
添加(“IsCollection”,true);
添加(“计数”,索引);
退货项目;
}
//如果属性是字符串,则停止遍历
if(propertyType.IsPrimitive | | propertyType.Equals(typeof(string)))
{
返回属性值;
}
PropertyInfo[]属性=
获取属性(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
if(properties.Any())
{
Dictionary resultDictionary=properties.ToDictionary(
SubsubpropertyInfo=>SubsubpropertyInfo.Name,
子类型PropertyInfo=>propertyValue==null
无效的
:(对象)Extensions.ConvertPropertyToDictionary(SubsubPropertyInfo,propertyValue));
resultDictionary.Add(“IsCollection”,false);
返回结果字典;
}
返回属性值;
}
私有静态字典ConvertIEnumerableToDictionary(IEnumerable可枚举)
{
var items=newdictionary();
int指数=0;
foreach(可枚举中的对象项)
{
//如果属性是字符串,则停止遍历
if(item.GetType().IsPrimitive | | item为字符串)
{
添加(index.ToString(),item);
}
其他的
{
Dictionary Dictionary=item.ToDictionary();
items.Add(index.ToString(),dictionary);
}
索引++;
}
添加(“IsCollection”,true);
添加(“计数”,索引);
退货项目;
}
}
例子
//测试对象定义
类TestClass
{
公共测试类()
{
this.TheNestedList=newlist(){newlist(){1,2,3,4},newlist(){11,22,33,44};
}
public List TheNestedList{get;set;}
}
//用法示例
静态void Main(字符串[]参数)
{
var testClass=新的testClass();
//将testClass实例转换为字典
Dictionary testClassDictionary=testClass.ToDictionary();
//消耗结果并
//再
// Test object definition
class TestClass
{
  public TestClass()
  {
    this.TheNestedList = new List<List<double>>() {new List<double>() {1, 2, 3, 4}, new List<double>() {11, 22, 33, 44}};
  }

  public List<List<double>> TheNestedList { get; set; }
}

// Usage example
static void Main(string[] args)
{
  var testClass = new TestClass();

  // Convert testClass instance to Dictionary<string, object>
  Dictionary<string, object> testClassDictionary = testClass.ToDictionary();

  // Consume the result and 
  // retrieve the outer List<List<double>>
  var nestedListProperty = testClassDictionary["NestedList"] as Dictionary<string, object>;

  if ((bool) nestedListProperty["IsCollection"])
  {
    // Retrieve the inner List<double>
    for (var index = 0; index < (int) theNestedListProperty["Count"]; index++)
    {
      var itemOfOuterList = theNestedListProperty[index.ToString()] as Dictionary<string, object>;
      if ((bool) itemOfOuterList["IsCollection"])
      {
        // Retrieve the double values
        for (var nestedListIndex = 0; nestedListIndex < (int) itemOfOuterList["Count"]; nestedListIndex++)
        {
          var innerListValue = (double) itemOfOuterList[nestedListIndex.ToString()];
        }
      }
    }
  }
}