使用反射初始化构造函数中的(列表)属性



我正在尝试使用反射初始化类(列表(中的所有属性:

public class EntitiesContainer
{
    public IEnumerable<Address> Addresses { get; set; }
    public IEnumerable<Person> People { get; set; }
    public IEnumerable<Contract> Contracts { get; set; }
    public EntitiesContainer()
    {
        var propertyInfo = this.GetType().GetProperties();
        foreach (var property in propertyInfo)
        {
            property.SetValue(property, Activator.CreateInstance(property.GetType()), null);
        }
    }
}

我收到异常:

没有

为没有参数的此对象定义任何构造函数。

我将不胜感激提示。

只要将属性定义为具体类型,就可以执行此操作。这实际上有效:

public class EntitiesContainer
{
    public List<Address> Addresses { get; set; }
    public List<Person> People { get; set; }
    public List<Contract> Contracts { get; set; }
    public EntitiesContainer()
    {
        var propertyInfo = this.GetType().GetProperties();
        foreach (var property in propertyInfo)
        {
            property.SetValue(this, Activator.CreateInstance(property.PropertyType));
        }
    }
}

不能创建IEnumerable<T>的实例,因为它是一个接口。

但是你为什么要这样做呢?最好使用 C#6 中引入的自动属性初始值设定项初始化属性:

public class EntitiesContainer
{
    public IEnumerable<Address> Addresses { get; set; } = new List<Address>;
    public IEnumerable<Person> People { get; set; } = new List<Address>;
    public IEnumerable<Contract> Contracts { get; set; } = new List<Address>;
}

一般来说,这里要创建的对象类型是property.PropertyType;而要设置值的对象是 this ,所以:

property.SetValue(this, Activator.CreateInstance(property.PropertyType), null);

但是!你的属性是IEnumerable<T>的,而不是List<T>的——不能创建一个接口,只能创建一个具体的类型。所以你必须做很多工作来解构泛型IEnumerable<Foo> Foo(var args = type.GetGenericTypeArguments()(和构造一个List<Foo>(typeof(List<>).MakeGenericType(args)(。或者只是将属性类型更改为List<T>

坦率地说,这样做会更容易:

public IEnumerable<Address> Addresses { get; set; } = new List<Address>();
public IEnumerable<Person> People { get; set; } = new List<Person>();
public IEnumerable<Contract> Contracts { get; set; } = new List<Contract>();

或:

public List<Address> Addresses { get; } = new List<Address>();
public List<Person> People { get; } = new List<Person>();
public List<Contract> Contracts { get; } = new List<Contract>();

总结一下,我想实现的是构造函数中调用的方法,如下所示:

    private void InitializeAllCollections()
    {
        var properties = this.GetType().GetProperties();
        foreach (var property in properties)
        {
            var genericType = property.PropertyType.GetGenericArguments();
            var creatingCollectionType = typeof(List<>).MakeGenericType(genericType);
            property.SetValue(this, Activator.CreateInstance(creatingCollectionType));
        }
    }

谢谢大家的帮助。 :)

我也有类似的需求:在为单元测试创建业务对象时,我想将所有未初始化的列表默认为新列表,这样如果测试需要向列表中添加某些内容,我就不必担心在那里初始化它。 与 OP 一样,我有太多的业务对象无法将它们全部更改为默认值。 我的解决方案是其他解决方案的混合;例外情况是我只想要 List 属性,并且仅当它们尚未初始化时:

    public static T DefaultLists<T>(this T obj)
    {
        var properties = obj.GetType().GetProperties().Where(q => q.PropertyType.Name == "List`1" && q.GetValue(obj) == null);
        foreach(var property in properties)
            property.SetValue(obj, Activator.CreateInstance(property.PropertyType));
        return obj;
    }

现在,我的示例对象创建者可以返回新的 businessObject.DefaultLists((;

相关内容

  • 没有找到相关文章

最新更新