public partial class ReturnHeader
{
public int ReturnHeaderId { get; set; }
public int CustomerId { get; set; }
public string InvoiceNo { get; set; }
public virtual Customer Customer { get; set; }
public virtual ICollection<ReturnDetail> ReturnDetails { get; set; }
}
public void TraverseThroughClass<T> (T entity) where T : class
{
try
{
var type = typeof(T);
PropertyInfo[] props = type.GetProperties();
foreach (PropertyInfo prop in props)
{
if (typeof(IEnumerable).IsAssignableFrom(prop.PropertyType))
{
此检查确定属性是否为列表。
问题1:如果为true,则将其投射到列表或任何集合中。 我想做的是,如果属性是一个将其强制转换为集合的集合,并且对于已强制转换的集合调用
TraverseThroughClass
/* Error casting into any collection*/
//var propertiesValues = prop.GetValue(entity) as IList;
var listType = GetCollectionItemType(prop.PropertyType);
foreach (var listItem in propertiesValues)
{
问题2:对于集合中的每个项目,请调用TraverseThroughClass(T实体)
}
}
else
{
Console.WriteLine("Prop Name : " + prop.Name + " Prop Value : "
+ prop.GetValue(entity, null));
}
}
}
catch (Exception e)
{
throw;
}
}
public static Type GetCollectionItemType(Type collectionType)
{
var types = collectionType.GetInterfaces()
.Where(x => x.IsGenericType
&& x.GetGenericTypeDefinition() == typeof(IEnumerable<>))
.ToArray();
return types.Length == 1 ? types[0].GetGenericArguments()[0] : null;
}
答案 0 :(得分:1)
您似乎正在尝试将ICollection
强制转换为IList
,但这可能有效也可能无效。运行时属性的值可能是未实现ICollection
的{{1}}。
如果此属性的运行时值实现IList
,它将起作用,但如果失败,则它将失败。
IList
由于您要检查属性类型是否可以从public virtual ICollection<ReturnDetail> ReturnDetails { get; set; }
进行分配,因此我们保持一致,并在各处使用它。
另一个困惑是IEnumerable
使用一个TraverseThroughClass
参数,但是在上面的语句中,您正在使用entity
来调用该属性。您是否要在this
上调用属性?那会更有意义。否则,它会切换-方法的一部分正在调用entity
的属性,而一部分正在调用entity
上的属性,this
是在其中调用该方法的类实例。
为解决这个问题,我将TraverseThroughClass
移到其自己的静态类中,并对entity
参数执行所有操作。我还删除了GetCollectionItemType
。它被调用了,但是调用的结果从未使用过,因此看起来好像我们不需要它。
这是您方法的修改版本,移到了自己的类中。 (请注意,我并没有解决此问题的大局,只是试图解决问题中的问题。)
public static class Traversal
{
public static void TraverseThroughClass<T>(T entity) where T : class
{
var type = typeof(T);
PropertyInfo[] props = type.GetProperties();
foreach (PropertyInfo prop in props)
{
if (typeof(IEnumerable).IsAssignableFrom(prop.PropertyType))
{
var propertiesValues = prop.GetValue(entity);
// What if the property value is null?
if (propertiesValues == null) continue;
var collection = propertiesValues as IEnumerable;
foreach (var listItem in collection)
{
// I don't know what you want to do with these.
// I'm just confirming that we're able to inspect them.
Debug.WriteLine("Success, we're iterating over the items!!");
}
}
else
{
Debug.WriteLine("Prop Name : " + prop.Name + " Prop Value : "
+ prop.GetValue(entity, null));
}
}
}
}
这仍然留下了您的方法将遍历InvoiceNo
的细节,因为它实现了IEnumerable
(它是字符的集合。)如果您不想这样做,则可以专门排除字符串或更详细地说明您要做的类型。
这时我可以执行以下代码:
var returnHeader = new ReturnHeader
{
ReturnDetails = new List<ReturnDetail>(
new ReturnDetail[] { new ReturnDetail(), new ReturnDetail() }),
InvoiceNo = "Invoice!"
};
Traversal.TraverseThroughClass(returnHeader);
...并且遍历将遍历InvoiceNo
中的字符和ReturnDetails
中的项目。