c# - 为运行时已知的属性调用通用方法
问题描述
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;
}
解决方案
看起来您正在尝试将 an 转换ICollection
为IList
,这可能会或可能不会起作用。运行时属性的值可能是ICollection
未实现的IList
。
如果此属性的运行时值实现IList
,它将起作用,但如果不是,它将失败。
public virtual ICollection<ReturnDetail> ReturnDetails { get; set; }
由于您正在检查属性类型是否可以从 分配IEnumerable
,所以让我们保持一致并在任何地方使用它。
另一个混淆是它TraverseThroughClass
接受一个entity
参数,但在上面的语句中你this
用来调用属性。你的意思是调用属性entity
吗?那会更有意义。否则它正在切换 - 方法的一部分正在调用 的属性,entity
而一部分正在调用 on 的属性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);
...并且遍历将遍历 in 中的字符InvoiceNo
和ReturnDetails
.
推荐阅读
- java - 需要有关制作包含 TableView 和 ScrollPane 的布局的建议
- javascript - 需要 HTMLElement API:与 IE6+ 等效的 click()
- android - 是否可以下载已编译的 c++ 二进制文件并在 iOS 上运行时加载它?
- swift - Swift - 如何限制几个特定的文本字段只允许插入 int?
- python - 在 Dockerfile 上运行安装 python 包
- c# - 在 Microsoft Teams 对话结束时清除对话状态的可能方法
- ionic-framework - 如何在 Ionic Mobile App 中测试哪个组件消耗更多电池
- python - 要导入,目录是否必须在 sys.path 中?
- javascript - Bootstrap Carousel 中的项目数返回 0
- java - 如何从另一个 LocalDate 中减去一个 localDate