Доступ к внутреннему типу ICollection <SomeInnerClass>через отражение в c # - PullRequest
1 голос
/ 28 октября 2011

Я пытаюсь установить свойство объекта, используя отражение.Свойство - ICollection - если экземпляр Collection не был создан, я хочу сделать это.У меня проблемы с тем, что у меня возникают проблемы с получением внутреннего типа ICollection

Это мой класс

public class Report(){
    public virtual ICollection<Officer> OfficerCollection { get; set; }
}

Я пытаюсь получить доступ к определенному ниже классу «Офицер» через рефлексию.

public class Officer(){
    public string Name{ get; set; }
}

Фрагмент кода

Report report = new Report()

PropertyInfo propertyInfo = report.GetType().GetProperty("OfficerCollection");
object entity = propertyInfo.GetValue(report, null);
if (entity == null)
{
    //How do I go about creating a new List<Officer> here?
}

Ответы [ 3 ]

3 голосов
/ 28 октября 2011

Дайте этому водовороту:

Report report = new Report();

PropertyInfo propertyInfo = report.GetType().GetProperty("Officer");
object entity = propertyInfo.GetValue(report, null);
if (entity == null)
{
    Type type = propertyInfo.PropertyType.GetGenericArguments()[0];
    Type listType = typeof(List<>).MakeGenericType(type);

    var instance = Activator.CreateInstance(listType);

    propertyInfo.SetValue(...);
}
2 голосов
/ 28 октября 2011

Прежде всего вы должны получить свойство Officer:

var propertyType = propertyInfo.PropertyType;

Затем вам нужно извлечь параметр общего типа:

var genericType = propertyType.GetGenericArguments()[0];

После этого создать общий список:

var listType = typeof(List<>).MakeGenericType(genericType);

Наконец, создайте новый экземпляр общего списка:

var listInstance = Activator.CreateInstance(listType);

и ... Веселитесь;)

EDIT:

Приятно иногда играть с отражением, но я рекомендую сделать это так:

public class Report()
{
    private ICollection<Officer> officers;

    public virtual ICollection<Officer> Officer 
    {
        get
        {
            if(officers == null)
                officers = new List<Officer>();

            return officers;
        }
        set { officers = value; }
    }
}
0 голосов
/ 28 октября 2011

Игнорируя проблему, что весь этот дизайн звучит ужасно, я постараюсь ответить на ваш вопрос. Вы можете найти тип недвижимости с Type type = ...GetProperty(...).PropertyType. Если тип был конкретным типом, а не интерфейсом, каким он является в настоящее время, вы можете использовать System.Activator.CreateInstance(type, null) - где null означает отсутствие аргументов конструктора - для создания экземпляра этого конкретного типа. Учитывая, что ваш тип свойства на самом деле является интерфейсом, вы не знаете, следует ли создавать список, массив, коллекцию или любой другой тип, который бы удовлетворял этому типу. Затем вам нужно будет использовать SetValue, чтобы назначить экземпляр свойству, но, конечно, мы не можем зайти так далеко.

Вы должны использовать эту информацию, чтобы переоценить свой дизайн, чтобы он не зависел от отражения, и вместо этого использовать общую параметризацию (посмотрите на ограничение new()) и ленивую инициализацию свойств (если вы думаете, что это имеет смысл - мы не против читатели.)

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