bogus how to dynamically hydrate all properties

25 Views Asked by At

I have a complex class tree graph and was looking to autopopulate all properties with mock data. I have the following code

    var faker = AutoInferRules<IATA_AIDX_FlightLegNotifRQ>();
var flight = faker.Generate();

static Faker<T> AutoInferRules<T>() where T : class, new()
{
    var faker = new Faker<T>();

    foreach (var property in typeof(T).GetProperties())
    {
        if (property.Name == "Schema")
        {
            continue;
        }

        try
        {
            if (property.PropertyType.IsClass && property.PropertyType != typeof(string))
            {
                // Recursively infer rules for nested classes
                var nestedFaker = typeof(Program)
                    .GetMethod("AutoInferRules", BindingFlags.NonPublic | BindingFlags.Static)
                    ?.MakeGenericMethod(property.PropertyType)
                    .Invoke(null, null);

                faker = faker.RuleFor(property.Name, _ => nestedFaker);
            }
            else if (property.PropertyType == typeof(Double))
            {
                faker = faker.RuleFor(property.Name, (f, _) => f.Random.Double());
            }
            else if (property.PropertyType == typeof(Nullable<Boolean>))
            {
                faker = faker.RuleFor(property.Name, (f, _) => f.Random.Bool());
            }
            
            else if (property.PropertyType.IsGenericType &&
                     typeof(IList<>).IsAssignableFrom(property.PropertyType.GetGenericTypeDefinition()))
            {
                // Handle the case where the property is a List of objects
                var elementType = property.PropertyType.GetGenericArguments()[0];
                
                //gets definition for GenerateList<T> based on the type of the property
                var generateListMethod = typeof(Program)
                    .GetMethods(BindingFlags.NonPublic | BindingFlags.Static).Last()
                    ?.MakeGenericMethod(elementType);
                
                var listExpression = Expression.Lambda<Func<T, List<T>>>(
                    Expression.Call(null, generateListMethod),
                    Expression.Parameter(typeof(T), "x")
                );

               
                faker = faker.RuleFor(property.Name,_ => listExpression);

            }
           
            else
            {
                // Generate rules for non-nested properties
                faker = faker.RuleFor(property.Name, (f, _) => f.Random.AlphaNumeric(10));
            }
        }
        catch (Exception ex)
        {
            Log.Logger.Error(ex, "error processing field {PropertyName}", property.Name);
        }
 
    }

    return faker;
}

static List<T> GenerateList<T>() where T : class, new()
{
    var faker = AutoInferRules<T>();
    return new List<T> { faker.Generate() };
}

I get an error on the line:

faker = faker.RuleFor(property.Name,_ => listExpression);

The error is:

Expression of type 'System.Collections.Generic.List1[RandomFlightDataGen.Model.IATA_AIDX_FlightLegNotifRQ.FlightLegType]' cannot be used for return type 'System.Collections.Generic.List1[RandomFlightDataGen.Model.IATA_AIDX_FlightLegNotifRQ.IATA_AIDX_FlightLegNotifRQ]

Which makes sense, because the initial call is with T where T is IATA_AIDX_FlightLegNotifRQ what I am unsure of is how do I for the Expression Lambda instead of using T use the type of the class on the property which I have inferred and created a MakeGenericMethod call for.

0

There are 0 best solutions below