将新 T 添加到空 List使用反射

发布于 2024-12-12 13:46:07 字数 1026 浏览 2 评论 0原文

我正在尝试使用反射将 Office 类的新实例添加到可能为空的列表中。

这些是我的课程

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

非常感谢!

I'm attempting to set add a new instance of an Officer class to a potentially empty list using reflection.

These are my classes

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

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

Simplified code snippet:

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

Much appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

绝不放开 2024-12-19 13:46:07

使用:

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

Use:

object o = Activator.CreateInstance(type); // "type" is the same variable you got a few lines above
((IList)entity).add(o);
勿忘心安 2024-12-19 13:46:07

您有两种选择:

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

You have two options:

1) Using dynamic:

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

2) Using Reflection:

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);
}
青芜 2024-12-19 13:46:07

这并不完全是您所要求的,但可以完成相同的任务。

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

This isn't quite what you asked for but may accomplish the same task.

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

If Officer doesn't have a default constructor then you could add a factory callback

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;
}
云之铃。 2024-12-19 13:46:07

只需将您的实体适当地键入为 List(或适当的更抽象类型(例如 IList))并正常使用即可:

entity = Activator.CreateInstance(constructedListType) as IList;

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

entity.Insert(0, officer);

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

Just type your entity appropriately as a List<Officer> (or an appropriately more abstract type (such as IList)) and use as normal:

entity = Activator.CreateInstance(constructedListType) as IList;

But no need to check whether to insert or not, just insert:

entity.Insert(0, officer);

I'm assuming (based on the fact that you already know how to create instances using reflection) you're not having trouble creating the instance of type Officer.

自此以后,行同陌路 2024-12-19 13:46:07

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

您可以轻松地在不使用反射的情况下完成:

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 实例(按其默认值)的列表

Edit after re-reading over your question: This doesn't directly answer your question but is rather a suggestion of a different implementation.

You can easily get by without using reflection:

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

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

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

}

Then calling e.g.:

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

you will have a list of 3 instances of YourClass by their default value

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文