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



我正在尝试使用反射在对象上设置属性。这个属性是一个ICollection——如果Collection还没有被实例化,我想要完成它。我的问题是,我有问题获得iccollection

的内部类型

这是我的类

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

试一下:

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

首先你必须得到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; }
    }
}

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

你应该利用这些信息来重新评估你的设计,不要依赖于反射,而是使用泛型参数化(看看new()约束)和属性的延迟初始化(如果你认为这是有意义的——我们不是读心术的人)

相关内容

  • 没有找到相关文章

最新更新