访问 ICollection的内部类型通过c#中的反射

发布于 2024-12-12 19:39:45 字数 662 浏览 3 评论 0原文

我正在尝试使用反射在对象上设置属性。 该属性是一个 ICollection - 如果该 Collection 尚未实例化,我想完成该操作。我的问题是我在获取 ICollection 的内部类型时遇到问题

这是我的类

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

我试图通过反射访问下面定义的“Officer”类代码

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

I'm attempting to set a property on an object using reflection.
The property is an ICollection - if the Collection has not been instantiated, I want to get that done. My problems is that I'm having issues getting the inner type of the ICollection

This is my class

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

I'm trying to access the 'Officer' class defined below through reflection

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

Code snippet

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

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

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

发布评论

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

评论(3

鲸落 2024-12-19 19:39:45

尝试一下:

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

Give this a whirl:

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(...);
}
少年亿悲伤 2024-12-19 19:39:45

首先,您必须获取 Officer 属性:

var propertyType = propertyInfo.PropertyType;

然后提取泛型类型参数:

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

之后调用创建泛型列表:

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

最后创建泛型列表的新实例:

var listInstance = Activator.CreateInstance(listType);

然后...玩得开心;)

编辑:

有时玩反射很好,但我建议你这样做:

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

First of all you have to get the of Officer property:

var propertyType = propertyInfo.PropertyType;

Then you to extract generic type parameter:

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

After that invoke create a generic list:

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

Finally create a new instance of generic list:

var listInstance = Activator.CreateInstance(listType);

and... Have fun ;)

EDIT:

It's nice to play sometimes with reflection, but I recommend you to do it this way:

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; }
    }
}
烏雲後面有陽光 2024-12-19 19:39:45

忽略整个设计听起来很糟糕的问题,我将尝试回答你的问题。您可以使用 Type type = ...GetProperty(...).PropertyType 查找属性的类型。如果类型是具体类型 - 而不是当前的接口 - 您可以使用 System.Activator.CreateInstance(type, null) - 其中 null 表示否构造函数参数 - 创建此具体类型的实例。鉴于您的属性类型实际上是一个接口,您不知道是否应该创建列表、数组、集合或任何其他类型来满足此类型。然后,您需要使用 SetValue 将实例分配给属性,但当然我们无法做到这一点。

您应该利用此信息重新评估您的设计,使其不依赖于反射,而是使用通用参数化(查看 new() 约束)和属性的延迟初始化(如果您认为这是有道理的 - 我们不是读心术的人。)

Ignoring the issue that this whole design sounds terrible, I'll try to answer your question. You can find the type of the property with Type type = ...GetProperty(...).PropertyType. If the type was a concrete type - instead of an interface as it currently is - you could then use System.Activator.CreateInstance(type, null) - where null means no constructor arguments - to create an instance of this concrete type. Given that your property type is actually an interface, you don't know whether you should be creating a list, array, collection or any other type that would satisfy this type. You would then need to use SetValue to assign the instance to the property, but of course we're not able to get this far.

You should take this information to reevaluate your design to not depend on reflection, and instead use generic parameterization (look at the new() constraint) and lazy initialization of properties (if you think that makes sense - we're not mind readers.)

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