将嵌套 class 转换为字典
Convert nested class to dictionary
我想将嵌套的 class 转换为漂亮的 key/value 字典,并保留每个 属性 的 class 名称和嵌套路径,以便于搜索之后。
这是我的例子class:
var agreement = new Agreement
{
ID = 101,
Description = "Convert to dictionary",
Customer = new Customer
{
FirstName = "John",
LastName = "Smith",
Age = 30,
Address = new List<Address>()
{
new Address
{
Name = "Los Angeles 1",
ZipCode = 25437
},
new Address
{
Name = "New York 25",
ZipCode = 25441
}
}
}
};
这是我在字典中预期的 key/value 输出:
KEY VALUE
Agreement.ID: 101
Agreement.Description: Convert to dictionary
Agreement.Customer.FirstName: John
Agreement.Customer.LastName: Smith
Agreement.Customer.Age: 30
Agreement.Customer.Address[0].Name: Los Angeles 1
Agreement.Customer.Address[0].ZipCode: 25437
Agreement.Customer.Address[1].Name: New York 25
Agreement.Customer.Address[1].ZipCode: 25441
有人知道我如何实现这一点吗?
(抱歉,我没有时间测试这个。)
您可以使用反射和递归编写解决方案。像这样的东西,在下面。
您需要添加空检查和其他退出情况,否则您将很快陷入无限循环。
这只是为了帮助您入门。
public Dictionary<string, string> MapToDictionary(object source, string name)
{
var dictionary = new Dictionary<string, string>();
MapToDictionaryInternal(dictionary, source, name);
return dictionary;
}
private void MapToDictionaryInternal(
Dictionary<string, string> dictionary, object source, string name)
{
var properties = source.GetType().GetProperties();
foreach(var p in properties)
{
var key = name + "." + p.Name;
object value = p.GetValue(source, null);
Type valueType = value.GetType();
if (valueType.IsPrimitive || valueType == typeof (String))
{
dictionary[key] = value.ToString();
}
else if (value is IEnumerable)
{
var i = 0;
foreach (object o in (IEnumerable) value)
{
MapToDictionaryInternal(dictionary, o, key + "[" + i + "]");
i++;
}
}
else
{
MapToDictionaryInternal(dictionary, value, key);
}
}
}
这样称呼它:
Dictionary<string, string> dictionary2 = MapToDictionary(agreement, "Agreement");
感谢 Buh Buh,他的解决方案非常有效。
只需添加一些配置并深入绕过循环。
// 定义方法
public class ObjectConvertInfo
{
public object ConvertObject { set; get; }
public IList<Type> IgnoreTypes { set; get; }
public IList<string> IgnoreProperties { set; get; }
public int MaxDeep { set; get; } = 3;
}
public Dictionary<string, string> ConvertObjectToDictionary(ObjectConvertInfo objectConvertInfo)
{
try
{
var dictionary = new Dictionary<string, string>();
MapToDictionaryInternal(dictionary, objectConvertInfo, objectConvertInfo.ConvertObject.GetType().Name, 0);
return dictionary;
}
catch (Exception e)
{
return null;
}
}
private void MapToDictionaryInternal(IDictionary<string, string> dictionary, ObjectConvertInfo objectConvertInfo, string name, int deep)
{
try
{
if (deep > objectConvertInfo.MaxDeep)
return;
var properties = objectConvertInfo.ConvertObject.GetType().GetProperties();
foreach (var propertyInfo in properties)
{
if (objectConvertInfo.IgnoreProperties.ContainIgnoreCase(propertyInfo.Name))
continue;
var key = name + "." + propertyInfo.Name;
var value = propertyInfo.GetValue(objectConvertInfo.ConvertObject, null);
if (value == null)
continue;
var valueType = value.GetType();
if (objectConvertInfo.IgnoreTypes.Contains(valueType))
continue;
if (valueType.IsPrimitive || valueType == typeof(String))
{
dictionary[key] = value.ToString();
}
else if (value is IEnumerable)
{
var i = 0;
foreach (var data in (IEnumerable)value)
{
MapToDictionaryInternal(dictionary, new ObjectConvertInfo
{
ConvertObject = data,
IgnoreTypes = objectConvertInfo.IgnoreTypes,
IgnoreProperties = objectConvertInfo.IgnoreProperties, MaxDeep = objectConvertInfo.MaxDeep
}, key + "[" + i + "]", deep + 1);
i++;
}
}
else
{
MapToDictionaryInternal(dictionary, new ObjectConvertInfo
{
ConvertObject = value,
IgnoreTypes = objectConvertInfo.IgnoreTypes,
IgnoreProperties = objectConvertInfo.IgnoreProperties, MaxDeep = objectConvertInfo.MaxDeep
}, key, deep + 1);
}
}
}
catch (Exception ex)
{
}
}
// 并调用
var result = cryptoService.ConvertObjectToDictionary(new ObjectConvertInfo
{
ConvertObject = objectToWrite,
IgnoreProperties = new List<string> { "PropertyA", "PropertyB"},
IgnoreTypes = new List<Type> { typeof(IntPtr), typeof(Delegate), typeof(Type) },
MaxDeep = 3
});
缺少方法的更新
public static bool ContainIgnoreCase(this IEnumerable<string> list, string value)
{
if (list == null || !list.Any())
return false;
if (value == null)
return false;
return list.Any(item => item.Equals(value, StringComparison.OrdinalIgnoreCase));
}
我想将嵌套的 class 转换为漂亮的 key/value 字典,并保留每个 属性 的 class 名称和嵌套路径,以便于搜索之后。
这是我的例子class:
var agreement = new Agreement
{
ID = 101,
Description = "Convert to dictionary",
Customer = new Customer
{
FirstName = "John",
LastName = "Smith",
Age = 30,
Address = new List<Address>()
{
new Address
{
Name = "Los Angeles 1",
ZipCode = 25437
},
new Address
{
Name = "New York 25",
ZipCode = 25441
}
}
}
};
这是我在字典中预期的 key/value 输出:
KEY VALUE
Agreement.ID: 101
Agreement.Description: Convert to dictionary
Agreement.Customer.FirstName: John
Agreement.Customer.LastName: Smith
Agreement.Customer.Age: 30
Agreement.Customer.Address[0].Name: Los Angeles 1
Agreement.Customer.Address[0].ZipCode: 25437
Agreement.Customer.Address[1].Name: New York 25
Agreement.Customer.Address[1].ZipCode: 25441
有人知道我如何实现这一点吗?
(抱歉,我没有时间测试这个。)
您可以使用反射和递归编写解决方案。像这样的东西,在下面。
您需要添加空检查和其他退出情况,否则您将很快陷入无限循环。 这只是为了帮助您入门。
public Dictionary<string, string> MapToDictionary(object source, string name)
{
var dictionary = new Dictionary<string, string>();
MapToDictionaryInternal(dictionary, source, name);
return dictionary;
}
private void MapToDictionaryInternal(
Dictionary<string, string> dictionary, object source, string name)
{
var properties = source.GetType().GetProperties();
foreach(var p in properties)
{
var key = name + "." + p.Name;
object value = p.GetValue(source, null);
Type valueType = value.GetType();
if (valueType.IsPrimitive || valueType == typeof (String))
{
dictionary[key] = value.ToString();
}
else if (value is IEnumerable)
{
var i = 0;
foreach (object o in (IEnumerable) value)
{
MapToDictionaryInternal(dictionary, o, key + "[" + i + "]");
i++;
}
}
else
{
MapToDictionaryInternal(dictionary, value, key);
}
}
}
这样称呼它:
Dictionary<string, string> dictionary2 = MapToDictionary(agreement, "Agreement");
感谢 Buh Buh,他的解决方案非常有效。 只需添加一些配置并深入绕过循环。
// 定义方法
public class ObjectConvertInfo
{
public object ConvertObject { set; get; }
public IList<Type> IgnoreTypes { set; get; }
public IList<string> IgnoreProperties { set; get; }
public int MaxDeep { set; get; } = 3;
}
public Dictionary<string, string> ConvertObjectToDictionary(ObjectConvertInfo objectConvertInfo)
{
try
{
var dictionary = new Dictionary<string, string>();
MapToDictionaryInternal(dictionary, objectConvertInfo, objectConvertInfo.ConvertObject.GetType().Name, 0);
return dictionary;
}
catch (Exception e)
{
return null;
}
}
private void MapToDictionaryInternal(IDictionary<string, string> dictionary, ObjectConvertInfo objectConvertInfo, string name, int deep)
{
try
{
if (deep > objectConvertInfo.MaxDeep)
return;
var properties = objectConvertInfo.ConvertObject.GetType().GetProperties();
foreach (var propertyInfo in properties)
{
if (objectConvertInfo.IgnoreProperties.ContainIgnoreCase(propertyInfo.Name))
continue;
var key = name + "." + propertyInfo.Name;
var value = propertyInfo.GetValue(objectConvertInfo.ConvertObject, null);
if (value == null)
continue;
var valueType = value.GetType();
if (objectConvertInfo.IgnoreTypes.Contains(valueType))
continue;
if (valueType.IsPrimitive || valueType == typeof(String))
{
dictionary[key] = value.ToString();
}
else if (value is IEnumerable)
{
var i = 0;
foreach (var data in (IEnumerable)value)
{
MapToDictionaryInternal(dictionary, new ObjectConvertInfo
{
ConvertObject = data,
IgnoreTypes = objectConvertInfo.IgnoreTypes,
IgnoreProperties = objectConvertInfo.IgnoreProperties, MaxDeep = objectConvertInfo.MaxDeep
}, key + "[" + i + "]", deep + 1);
i++;
}
}
else
{
MapToDictionaryInternal(dictionary, new ObjectConvertInfo
{
ConvertObject = value,
IgnoreTypes = objectConvertInfo.IgnoreTypes,
IgnoreProperties = objectConvertInfo.IgnoreProperties, MaxDeep = objectConvertInfo.MaxDeep
}, key, deep + 1);
}
}
}
catch (Exception ex)
{
}
}
// 并调用
var result = cryptoService.ConvertObjectToDictionary(new ObjectConvertInfo
{
ConvertObject = objectToWrite,
IgnoreProperties = new List<string> { "PropertyA", "PropertyB"},
IgnoreTypes = new List<Type> { typeof(IntPtr), typeof(Delegate), typeof(Type) },
MaxDeep = 3
});
缺少方法的更新
public static bool ContainIgnoreCase(this IEnumerable<string> list, string value)
{
if (list == null || !list.Any())
return false;
if (value == null)
return false;
return list.Any(item => item.Equals(value, StringComparison.OrdinalIgnoreCase));
}