Перечислите ICollection <T>свойство класса, используя Reflection - PullRequest
1 голос
/ 20 сентября 2010

Я пытаюсь создать базовый класс для своих объектов POCO в .NET 4, который будет иметь метод Include (string path), где path - это «.» путь навигации с разделителями для вложенных свойств ICollection наследуемого класса.

Например, с учетом следующих классов;

public class Region
{
    public string Name { get; set; }
    public ICollection<Country> Countries { get; set; }
}
public partial class Region : EntityBase<Region> {}

public class Country
{
    public string Name { get; set; }
    public ICollection<City> Cities { get; set; }
}
public partial class Country : EntityBase<Country> {}

public class City
{
    public string Name { get; set; }
}
public partial class City : EntityBase<City> {}

Я хочу иметь возможность сделать что-то вроде этого;

Region region = DAL.GetRegion(4);
region.Include("Countries.Cities");

Пока у меня есть следующее:

public class EntityBase<T> where T : class 
{
    public void Include(string path)
    {
        // various validation has been omitted for brevity
        string[] paths = path.Split('.');
        int pathLength = paths.Length;
        PropertyInfo propertyInfo = type(T).GetProperty(paths[0]);
        object propertyValue = propertyInfo.GetValue(this, null);
        if (propertyValue != null)
        {
            Type interfaceType = propertyInfo.PropertyType;
            Type entityType = interfaceType.GetGenericArguments()[0];

            // I want to do something like....
            var propertyCollection = (ICollection<entityType>)propertyValue;
            foreach(object item in propertyCollection)
           {
               if (pathLength > 1)
               {
                   // call Include method of item for nested path
               }
           }
        }
    }
}

Понятно, что строка "var list = ...>" не работает, но вы надеетесь получить суть, и foreach не будет работать, если не будет перечислимо свойствоCollection.

Так что это последний бит, то есть, как мне перечислить свойство ICollection класса, когда я не знаю тип T до времени выполнения?

Спасибо

Ответы [ 2 ]

1 голос
/ 20 сентября 2010

Для этого вам не нужно отражение.Для того, чтобы перечислить его, вам нужен только IEnumerable.ICollection<T> наследует IEnumerable, поэтому все ваши коллекции будут перечислимыми.Следовательно,

var propertyCollection = (IEnumerable) propertyValue;
foreach (object item in propertyCollection)
    // ...

будет работать.

0 голосов
/ 20 сентября 2010

Обобщения обычно используются, когда клиент может разрешить универсальный тип в время компиляции .Оставляя это в стороне, поскольку все, что вам нужно сделать, это перечислить propertyCollection (рассматривая каждый элемент последовательности просто как System.Object), все, что вам нужно сделать, это:

var propertyCollection = (IEnumerable)propertyValue;
foreach(object item in propertyCollection)
{
    ...
}    

Это совершенно безопаснопоскольку ICollection<T> расширяется IEnumerable<T>, что, в свою очередь, расширяет IEnumerable.То, что T на самом деле заканчивается во время выполнения, не имеет значения, поскольку цикл требует только object.

Реальный вопрос: достаточно ли System.Object для ваших целей внутри цикла?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...