实例化包含所有对象属性的类型的实例并遵守继承

时间:2017-04-26 19:34:40

标签: c# reflection json.net

我不确定该标题是否反映了实际问题,所以让我解释一下。有没有办法实例化一个类并递归实例化所有类的属性?

例如:

public class Base
{
    public int BaseValue{ get; set;} 
}

public class Extended : Base
{
    public int ExtendedValue{ get; set;}
    public AnotherExtendedClass AnotherClass { get; set;}
}

我想创建一个由Extended的空实例组成的json有效负载,其中所有默认值和属性都已实例化。并使用它:

string representation = Test.CreateDefaultEmptyJson(Extended);

public static string CreateDefaultEmptyJson(Type type)
{
    JsonSerializerSettings settings = new JsonSerializerSettings().Configure();
    var defaultInstance= Activator.CreateInstance(type);
    return JsonConvert.SerializeObject(defaultInstance, settings);
}

输出不包含Extended类属性。我回来了:

{
    "BaseValue":0
}

当我真的想看(或类似的东西)时:

{
    "BaseValue":0,
    {
         "ExtendedValue":0,
         {
             ...
         }
    }
}

我想我可以递归迭代所有类型的Extended并调用默认构造函数,但是,在我走这条路之前,可能会有几行代码来完成相同的工作。

2 个答案:

答案 0 :(得分:1)

这个匆匆写的课程开始解决你的问题。它返回可返回引用类型的可设置属性,并以递归方式遍历它们,根据需要创建实例。

它不包括

  • 索引属性
  • 递归深度

您可能最好只在属性本身上设置默认值,以便不会使用不需要的空值创建类。

public class PropertyPopulator
{
    public void PopulateProperties(object target)
    {
        var properties = target.GetType()
            .GetProperties(BindingFlags.Instance | BindingFlags.Public)
            .Where(p => p.PropertyType.IsClass && p.CanWrite && p.CanRead);
        foreach (var property in properties)
        {
            var propertyValue = property.GetValue(target);
            if (propertyValue == null)
            {
                var constructor = property.PropertyType.GetConstructor(new Type[] { });
                if (constructor != null)
                {
                    propertyValue = constructor.Invoke(new object[] { });
                    property.SetValue(target, propertyValue);
                    PopulateProperties(propertyValue);
                }
            }
        }
    }
}

答案 1 :(得分:1)

据我所知,除了编写自己的递归方法之外,没有一种内置的方法。
但是,假设:

  1. 你的类都有无参数(默认)构造函数,
  2. 非原始属性都是具体类型(不是接口)和
  3. 你的班级结构中没有任何参考循环,
  4. 然后你可以用大约十几行代码创建这样一个方法:

    public static string CreateDefaultEmptyJson(Type type)
    {
        return JsonConvert.SerializeObject(RecursiveCreateInstance(type), Formatting.Indented);
    }
    
    public static object RecursiveCreateInstance(Type type)
    {
        object obj = null;
        ConstructorInfo ctor = type.GetConstructor(Type.EmptyTypes);
        if (ctor != null)
        {
            obj = ctor.Invoke(null);
            foreach (PropertyInfo prop in type.GetProperties())
            {
                Type propType = prop.PropertyType;
                if (prop.CanWrite && propType.IsClass)
                {
                    prop.SetValue(obj, RecursiveCreateInstance(propType));
                }
            }
        }
        return obj;
    }
    

    小提琴:https://dotnetfiddle.net/3VMTsC

    如果上述假设不成立,那么事情就会变得复杂起来。如果您遇到需要轻松创建虚假对象以进行测试的问题,那么您可能需要考虑使用mocking framework