我正在尝试使用反射在对象上设置属性。 该属性是一个ICollection - 如果Collection尚未实例化,我想完成它。我的问题是我在获取ICollection的内部类型时遇到问题
这是我的班级
public class Report(){
public virtual ICollection<Officer> OfficerCollection { get; set; }
}
我正试图通过反思
访问下面定义的'官员'类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?
}
答案 0 :(得分:3)
给它一个旋转:
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(...);
}
答案 1 :(得分:2)
首先,您必须获得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; }
}
}
答案 2 :(得分:0)
忽略整个设计听起来很糟糕的问题,我会尽力回答你的问题。您可以使用Type type = ...GetProperty(...).PropertyType
找到属性的类型。如果类型是具体类型 - 而不是当前的接口 - 那么您可以使用System.Activator.CreateInstance(type, null)
- 其中null
表示没有构造函数参数 - 创建此具体类型的实例。鉴于您的属性类型实际上是一个接口,您不知道是应该创建列表,数组,集合还是满足此类型的任何其他类型。然后,您需要使用SetValue将实例分配给属性,但当然我们无法做到这一点。
您应该使用此信息重新评估您的设计,使其不依赖于反射,而是使用通用参数化(查看new()
约束)和属性的延迟初始化(如果您认为有意义 - 我们是不介意读者。)