C# 将新T添加到空列表<;T>;使用反射

C# 将新T添加到空列表<;T>;使用反射,c#,reflection,C#,Reflection,我试图使用反射将一个军官类的新实例添加到一个可能为空的列表中 这些是我的课 public class Report(){ public virtual ICollection<Officer> Officer { get; set; } } public class Officer(){ public string Name{ get; set; } } 公共类报告(){ 公共虚拟ICollection Officer{get;set;} } 公职人员(){ 公共

我试图使用反射将一个军官类的新实例添加到一个可能为空的列表中

这些是我的课

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

public class Officer(){
    public string Name{ get; set; }
}
公共类报告(){
公共虚拟ICollection Officer{get;set;}
}
公职人员(){
公共字符串名称{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)
}
报告=新报告()
PropertyInfo PropertyInfo=report.GetType().GetProperty(“官员”);
对象实体=propertyInfo.GetValue(报告,空);
if(实体==null)
{
//获取列表的内部类型-Officer类
Type Type=propertyInfo.PropertyType.GetGenericArguments()[0];
var listType=类型(列表);
var constructedListType=listType.MakeGenericType(类型);
entity=Activator.CreateInstance(constructedListType);
}
//该实体现在是列表,或者刚刚创建,或者包含
//军官
//我想检查名单上有多少官员,如果没有,请插入一名
//伪代码:
如果(entity.count=0)
{
entity.add(类型的新实例)
}
非常感谢

使用:

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

只需以
列表
(或更为抽象的适当类型(如
IList
)的形式适当地键入实体,并正常使用:

entity = Activator.CreateInstance(constructedListType) as IList;
但无需检查是否插入,只需插入:

entity.Insert(0, officer);

我假设(基于您已经知道如何使用反射创建实例的事实)在重新阅读您的问题后,您在创建类型为
Officer
的实例时没有遇到问题:这并不是直接回答您的问题,而是建议使用不同的实现

无需使用反射即可轻松通过:

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

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

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

}
公共类TestContainer
{
私有只读列表_List;
公共测试容器()
{
_列表=新列表();
}
公共无效添加()
{
_列表。添加(默认值(T));
}
}
然后打电话,例如:

var t = new TestContainer<YourClass>();
t.Add();
t.Add();
t.Add();
var t=newtestcontainer();
t、 添加();
t、 添加();
t、 添加();
您将有一个包含3个默认值的类实例的列表

您有两个选项:

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

这不是你想要的,但可能完成同样的任务

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

实体是一个对象,但它没有add方法-我如何将其转换为List?这家伙在编译时没有该类型。在这种情况下,他们可以对
as
子句使用更抽象的类型,或者直接转换-但原则上,它完全相同。请欣赏-问题显然过于简化了,我不想讨论我使用反射的原因,但是谢谢你的评论!
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;
}