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