Похоже, вы пытаетесь разыграть ICollection
как IList
, что может или не может работать.Значение свойства во время выполнения может быть ICollection
, которое не реализует 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
.