gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 15:13:33 24 4
gpt4 key购买 nike

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

我考虑过使用 json.net,但快速检查后发现没有人要求完全相同的东西。

SSF.Mod类的缩减版本:

namespace SSF
{
public class FileWithHash
{
public string PrivatePath { get; set; }
public FileWithHash(string sharedPath, string hash)
{
PrivatePath = sharedPath; Hash = hash;
}
}
public class Mod
{
[JsonIgnore]
private Game Game { get; set; }
public bool Disabled {
get { ... }
}
public string Id { get; set; }
public DirectoryInfo Directory { get; set; }
public FileWithHash GroFile { get; set; }
public FileWithHash Thumbnail { get; set; }
public Publishedfiledetail Details { get; set; }
public List<string> Tags { get {
if (Details is null) return null;
var ret = new List<string>();
foreach (var tag in Details.tags) {
ret.Add(tag.tag);
}
return ret;
} }
}
}

将示例实例缩减为 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 :

Mod mod = new Mod();

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

编辑

以下方法将类型及其完整声明类型树转换为 Dictionary<string, object>

备注

默认KeyDictionary<string, object>是属性名。

集合被转换为 Dictionary<string, object> Key在哪里是项目的索引。
这种字典的最后一项是 Key 所在的计数。是"Count" .
确定是否 Dictionary<string, object>是一个使用 Key 的集合"IsCollection"它返回一个 bool 值。

您可以使用此扩展方法:

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;
}
}

例子

// 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()];
}
}
}
}
}

关于c# - 将类实例转换为字典以进行迭代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57845289/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com