Добавление нового T в пустой список <T>с использованием отражения - PullRequest
1 голос
/ 31 октября 2011

Я пытаюсь установить добавление нового экземпляра класса Officer в потенциально пустой список, используя отражение.

Это мои занятия

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

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

Упрощенный фрагмент кода:

Report report = new Report()

PropertyInfo propertyInfo = report.GetType().GetProperty("Officer");
object entity = propertyInfo.GetValue(report, null);
if (entity == null)
{
    //Gets the inner type of the list - the Officer class
    Type type = propertyInfo.PropertyType.GetGenericArguments()[0];
    var listType = typeof(List<>);
    var constructedListType = listType.MakeGenericType(type);
    entity = Activator.CreateInstance(constructedListType);
}
//The entity is now List<Officer> and is either just created or contains a list of
//Officers
//I want to check how many officers are in the list and if there are none, insert one
//Pseudo code:
if (entity.count = 0)
{
    entity.add(new instance of type)
}

Очень ценится!

Ответы [ 5 ]

1 голос
/ 31 октября 2011

Это не совсем то, что вы просили, но может выполнить ту же задачу.

public static ICollection<T> EnsureListExistsAndHasAtLeastOneItem(ICollection<T> source)
    where T : Officer, new()
{
    var list = source ?? new List<T>();
    if( list.Count == 0 ) list.Add(new T());
    return list;
}

Если у Officer нет конструктора по умолчанию, вы можете добавить обратный вызов фабрики

public static ICollection<T> EnsureListExistsAndHasAtLeastOneItem
   (ICollection<T> source, Func<T> builder)
    where T : Officer
{
    var list = source ?? new List<T>();
    if( list.Count == 0 ) list.Add(builder());
    return list;
}
1 голос
/ 31 октября 2011

У вас есть два варианта:

1) Использование динамического:

dynamic list = entity;
if (list.Count = 0)
{
    list.Add(new instance of type)
}

2) Использование отражения:

var countProp = entity.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).First(p => p.Name == "Count");
var count = (int)countProp.GetValue(entity,null);

if(count == 0)
{
   var method = entity.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public).First(m => m.Name == "Add");
   method.Invoke(entity,new instance of type);
}
1 голос
/ 31 октября 2011

Использование:

object o = Activator.CreateInstance(type); // "type" is the same variable you got a few lines above
((IList)entity).add(o);
0 голосов
/ 31 октября 2011

Изменить после перечитывания вашего вопроса: это не дает прямого ответа на ваш вопрос, а скорее является предложением другой реализации.

Вы можете легко обойтись без использования отражения:

public class TestContainer<T>
{
    private readonly List<T> _list;

    public TestContainer()
    {
        _list = new List<T>();
    }

    public void Add()
    {
        _list.Add(default(T));
    }

}

Затем, позвонив, например:

var t = new TestContainer<YourClass>();
t.Add();
t.Add();
t.Add();

, у вас будет список из 3 экземпляров YourClass с их значением по умолчанию

0 голосов
/ 31 октября 2011

Просто введите вашу сущность соответствующим образом как List<Officer> (или соответственно более абстрактный тип (такой как IList)) и используйте как обычно:

entity = Activator.CreateInstance(constructedListType) as IList;

Но не нужно проверять, вставлять или нет, просто вставьте:

entity.Insert(0, officer);

Я предполагаю (основываясь на том факте, что вы уже знаете, как создавать экземпляры с помощью отражения), у вас не возникнет проблем при создании экземпляра типа Officer.

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