我从api获得了一些动态数据,我想使用反射强烈地键入这些数据以在我的应用中重用。 我有对象的三个层次。
我想使用反射将相同类型的特定属性组合到集合中。
具有以下课程:
第1级:
public sealed class DynamicData
{
[JsonProperty(propertyName: "PersonInfo")]
public DynamicDataPersonInfo PersonInfo { get; set; }
[JsonProperty(propertyName: "Location")]
public DynamicDataLocation Location { get; set; }
}
第2级:
public sealed class DynamicDataPersonInfo
{
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("properties")]
public DynamicDataPersonInfoProperties Properties { get; set; }
[JsonProperty("required")]
public string[] PersonInfoRequired { get; set; }
}
public sealed class DynamicDataLocation
{
[JsonProperty(propertyName: "title")]
public string Title { get; set; }
[JsonProperty(propertyName: "type")]
public string Type { get; set; }
[JsonProperty(propertyName: "properties")]
public DynamicDataLocationProperties Properties { get; set; }
[JsonProperty(propertyName: "required")]
public string[] LocationRequired { get; set; }
}
第3级:
public sealed class DynamicDataLocationProperties
{
[JsonProperty(propertyName: "BuildingNumber")]
public DynamicDataFieldInfo BuildingNumber { get; set; }
[JsonProperty(propertyName: "UnitNumber")]
public DynamicDataFieldInfo UnitNumber { get; set; }
[JsonProperty(propertyName: "StreetName")]
public DynamicDataFieldInfo StreetName { get; set; }
[JsonProperty(propertyName: "StreetType")]
public DynamicDataFieldInfo StreetType { get; set; }
[JsonProperty(propertyName: "City")]
public DynamicDataFieldInfo City { get; set; }
[JsonProperty(propertyName: "StateProvinceCode")]
public DynamicDataFieldInfo StateProvinceCode { get; set; }
[JsonProperty(propertyName: "PostalCode")]
public DynamicDataFieldInfo PostalCode { get; set; }
}
public sealed class DynamicDataPersonInfoProperties
{
[JsonProperty(propertyName: "FirstGivenName")]
public DynamicDataFieldInfo FirstGivenName { get; set; }
[JsonProperty(propertyName: "MiddleName")]
public DynamicDataFieldInfo MiddleName { get; set; }
[JsonProperty(propertyName: "FirstSurName")]
public DynamicDataFieldInfo FirstSurName { get; set; }
[JsonProperty(propertyName: "DayOfBirth")]
public DynamicDataFieldInfo DayOfBirth { get; set; }
[JsonProperty(propertyName: "MonthOfBirth")]
public DynamicDataFieldInfo MonthOfBirth { get; set; }
[JsonProperty(propertyName: "YearOfBirth")]
public DynamicDataFieldInfo YearOfBirth { get; set; }
}
最终级别:
public sealed class DynamicDataFieldInfo
{
[JsonProperty(propertyName: "type")]
public string Type { get; set; }
[JsonProperty(propertyName: "description")]
public string Description { get; set; }
[JsonProperty(propertyName: "label")]
public string Label { get; set; }
}
我试图使这种泛型成为可能,并使用反射,但是对于每个级别,我都使用foreach循环。您知道这是怎么回事,在我看来代码看起来很糟糕:
private IReadOnlyList<DynamicProperty> CombineProperties(DynamicData deserializedRawData)
{
List<DynamicProperty> combinedDynamicProperties = new List<DynamicProperty>();
// dynamic data
foreach (PropertyInfo propertiyofDynamicData in deserializedRawData.GetType()
.GetProperties())
{
// dynamic data lower level
foreach (PropertyInfo propertyOfDynamicDataMember in propertiyofDynamicData.GetType()
.GetProperties()
.Where(predicate: x => x.Name == "Properties"))
{
foreach (PropertyInfo propertyOfFieldInfo in propertyOfDynamicDataMember.GetType()
.GetProperties())
{
DynamicDataFieldInfo dynamicDataFieldInfo = propertyOfFieldInfo.GetValue(propertyOfDynamicDataMember) as DynamicDataFieldInfo;
combinedDynamicProperties.Add(new DynamicProperty {DynamicDataFieldInfo = dynamicDataFieldInfo, GroupType = FormHelper.GetFormGroupType(propertiyofDynamicData.Name)});
}
}
}
return combinedDynamicProperties;
}
有没有办法避免这种可怕的循环?
答案 0 :(得分:2)
因此,我尝试为您的代码创建递归形式,但是可惜的是,循环中的每个步骤之间的差异太大,并且您在最终选择的对象中引用了第一个循环。相反,这是我要进行的三个更改:
更改将如下所示:
private IReadOnlyList<DynamicProperty> CombineProperties(DynamicData deserializedRawData)
{
List<DynamicProperty> combinedDynamicProperties = new List<DynamicProperty>();
// dynamic data
foreach (PropertyInfo propertiyofDynamicData in deserializedRawData.GetType()
.GetProperties())
{
object formGroup = propertiyofDynamicData.GetValue(deserializedRawData);
var formGroupType = FormHelper.GetFormGroupType(propertiyofDynamicData.Name);
// dynamic data lower level
PropertyInfo propertyOfDynamicDataMember = propertiyofDynamicData.GetType().GetProperty("Properties");
object propertiesGroup = propertyOfDynamicDataMember.GetValue(formGroup);
foreach (PropertyInfo propertyOfFieldInfo in propertyOfDynamicDataMember.GetType()
.GetProperties())
{
if (propertyOfFieldInfo.GetValue(propertiesGroup) is DynamicDataFieldInfo dynamicDataFieldInfo)
combinedDynamicProperties.Add(new DynamicProperty {DynamicDataFieldInfo = dynamicDataFieldInfo, GroupType = formGroupType });
}
}
return combinedDynamicProperties;
}
编辑:再三考虑,我们可以将其压缩为一个相当整齐的LINQ表达式
private IReadOnlyList<DynamicProperty> CombineProperties(DynamicData deserializedRawData)
{
return (from formGroupProp in deserializedRawData.GetType().GetProperties()
let formGroup = formGroupProp.GetValue(deserializedRawData)
let formGroupType = FormHelper.GetFormGroupType(formGroupProp.Name)
let properties = formGroupProp.GetType().GetProperty("Properties").GetValue(formGroup)
from dProp in properties.GetType().GetProperties()
let fieldInfo = dProp.GetValue(properties) as DynamicDataFieldInfo
where fieldInfo is DynamicDataFieldInfo
select new DynamicProperty { DynamicDataFieldInfo = fieldInfo, GroupType = formGroupType }).ToList()
}
编辑2:通过添加反射扩展,我们可以进一步简化所讨论的方法:(注意:将它们放在仅适用于此类特殊情况的名称空间中,否则它们会污染自动完成任何对象)
static class ReflectionExtensions
{
public static IEnumerable<object> AllProperties(this object root)
{
return root.GetType().GetProperties().Select((p) => p.GetValue(root));
}
public static IEnumerable<T> AllProperties<T>(this object root)
{
return root.GetType().GetProperties().Where((p) => p.GetType() == typeof(T)).Select((p) => p.GetValue(root));
}
public static object Property(this object root, string propName)
{
return root.GetType().GetProperty(propName)?.GetValue(root);
}
}
private IReadOnlyList<DynamicProperty> CombineProperties(DynamicData deserializedRawData)
{
return (from formGroup in deserializedRawData.AllProperties()
let formGroupType = FormHelper.GetFormGroupType(formGroup.GetType().Name)
let properties = formGroup.Property("Properties")
from fieldInfo in properties?.AllProperties<DynamicDataFieldInfo>() ?? Enumerable.Empty<PropertyInfo>()
select new DynamicProperty { DynamicDataFieldInfo = fieldInfo, GroupType = formGroupType }).ToList()
}