我正在尝试构建一个将对象转换为ExpandoObjects的泛型方法,我可以处理所有情况,除非其中一个属性是数组。
public static ExpandoObject ToExpando(this object AnonymousObject) {
dynamic NewExpando = new ExpandoObject();
foreach (var Property in AnonymousObject.GetType().GetProperties()) {
dynamic Value;
if (IsPrimitive(Property.PropertyType)) {
Value = Property.GetValue(AnonymousObject);
} else if (Property.PropertyType.IsArray) {
dynamic ArrayProperty = new List<dynamic>();
var ArrayElements = (Array)Property.GetValue(AnonymousObject);
for (var i = 0; i < ArrayElements.Length; i++) {
var Element = ArrayElements.GetValue(i);
if (IsPrimitive(Element.GetType())) {
ArrayProperty.Add(Element);
} else {
ArrayProperty.Add(ToExpando(Element));
}
}
Value = ArrayProperty;//.ToArray();
} else {
Value = ToExpando(Property.GetValue(AnonymousObject));
}
((IDictionary<string, object>) NewExpando)[Property.Name] = Value;
}
return NewExpando;
}
private static bool IsPrimitive(System.Type type) {
while (type.IsGenericType && type.GetGenericTypeDefinition() == typeof (Nullable<>)) {
// nullable type, check if the nested type is simple.
type = type.GetGenericArguments()[0];
}
return type.IsPrimitive || type.IsEnum || type.Equals(typeof (string)) || type.Equals(typeof (decimal));
}
任何数组的属性似乎都不是动态对象,当我在剃刀模板上使用它时,数组元素和属性不可见。
例如,如果我这样做:
var EmailParams = new {
Parent = new {
Username = "User1",
},
Students = new [] {new {Username = "Student1", Password = "Pass1"} }
};
正如您所看到的,顶部的匿名对象有一个学生数组,但转换后的ExpandoObject没有。
有没有人对我如何更改代码以在ExpandoObject中添加对数组/列表的支持有任何见解?
谢谢!
答案 0 :(得分:1)
创建像
这样的对象时var person = new
{
FirstName = "Test",
LastName = new List<Person>() { new Person()
{
FirstName = "Tes2"
} }
};
LastName是一个通用列表,Property.PropertyType.IsArray在该情况下返回false。因此,您尝试添加
的逻辑不会对您的“数组/列表”进行处理dynamic ArrayProperty = new List<dynamic>();
var ArrayElements = (Array)Property.GetValue(AnonymousObject);
for (var i = 0; i < ArrayElements.Length; i++) {
var Element = ArrayElements.GetValue(i);
if (IsPrimitive(Element.GetType())) {
ArrayProperty.Add(Element);
} else {
ArrayProperty.Add(ToExpando(Element));
}
}
希望这有帮助
只需一句话,你不需要在if(Property.Property.Type.IsArray)
原始值的逻辑内再次检查,你做到了,这是递归的停止条件之一。下面是相同的代码,区别于我提到
public static ExpandoObject ToExpando(this object AnonymousObject)
{
dynamic NewExpando = new ExpandoObject();
foreach (var Property in AnonymousObject.GetType().GetProperties())
{
dynamic Value;
if (IsPrimitive(Property.PropertyType))
{
Value = Property.GetValue(AnonymousObject);
}
else if (Property.PropertyType.IsArray)
{
var ArrayProperty = new List<ExpandoObject>();
var elements = Property.GetValue(AnonymousObject) as IEnumerable;
//is the same as foreach all elements calling to Expando and adding them to elemenstArray
if (elements != null)
ArrayProperty.AddRange(from object elem in elements select ToExpando(elem));
Value = ArrayProperty;
}
else
{
Value = ToExpando(Property.GetValue(AnonymousObject));
}
((IDictionary<string, object>)NewExpando)[Property.Name] = Value;
}
return NewExpando;
}