使用反射</t>将新T添加到空List <t>

时间:2011-10-31 14:55:08

标签: c# reflection

我正在尝试使用反射将一个新的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 个答案:

答案 0 :(得分:1)

使用:

object o = Activator.CreateInstance(type); // "type" is the same variable you got a few lines above
((IList)entity).add(o);

答案 1 :(得分:1)

您有两种选择:

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);
}

答案 2 :(得分:1)

这不是你要求的,但可以完成同样的任务。

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;
}

答案 3 :(得分:0)

只需将您的实体恰当地命名为List<Officer>(或更合适的抽象类型(例如IList))并正常使用:

entity = Activator.CreateInstance(constructedListType) as IList;

但无需检查是否插入,只需插入:

entity.Insert(0, officer);

我假设(基于您已经知道如何使用反射创建实例的事实),您在创建Officer类型的实例时没有遇到任何问题。

答案 4 :(得分:0)

重新阅读您的问题后进行编辑:这不是直接回答您的问题,而是建议采用不同的实施方式。

您可以轻松使用反射:

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实例的列表