I'm not sure if that title is reflective of the actual question, so let me explain. Is there a way to instantiate a class and recursively instantiate all properties that are classes?
For example :
public class Base
{
public int BaseValue{ get; set;}
}
public class Extended : Base
{
public int ExtendedValue{ get; set;}
public AnotherExtendedClass AnotherClass { get; set;}
}
I would like to create a json payload comprised of an empty instance of Extended
with all default values and properties instantiated. And use it like:
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);
}
The output does not include the Extended
class properties. I get back :
{
"BaseValue":0
}
When I would really like to see ( or something similar ):
{
"BaseValue":0,
{
"ExtendedValue":0,
{
...
}
}
}
I suppose I could recursively iterate all types of Extended
and call the default constructor, however, before I go down that road there may be a few lines of code to accomplish the same.
This hastily-written class begins to address your question. It returns the settable properties which return reference types and walks through them recursively, creating instances as needed.
It doesn't cover
You may be better off just setting defaults on the properties themselves so that the class won't be created with undesirable nulls.
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);
}
}
}
}
}
As far as I know there is not a built-in way to do this short of writing your own recursive method.
However, assuming that:
then you can create such a method in about a dozen lines of code:
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;
}
Fiddle: https://dotnetfiddle.net/3VMTsC
If the above assumptions don't hold, then things get complicated fast. If you're running into issues where you need an easy way to create fake objects for testing purposes, then you might want to look into using a mocking framework .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.