使用Bogus反射生成假数据时动态表达式参数数量错误求助
问题原因及解决方法
直接报错原因
你在构建表达式调用GenerateList<T>时,错误地传递了一个额外参数(Expression.New(generateListMethod!.ReturnType)),但GenerateList<T>是无参静态方法,参数数量不匹配直接触发了报错。
除此之外,代码还有几处逻辑问题需要修正:
其他问题点
- 获取
GenerateList方法的方式不可靠:用GetMethods().Last()依赖方法定义顺序,容易拿到错误方法,应该通过方法名精确获取。 - Lambda表达式类型不匹配:Bogus的
RuleFor要求第二个参数是Func<Faker, T, TProperty>类型委托,但你定义的Expression.Lambda<Func<T, List<T>>>不符合这个签名。 - 嵌套类赋值错误:直接把
Faker<T>对象赋值给属性,而不是调用Generate()方法生成实例。 - 传递表达式对象而非委托:把未编译的
Expression对象传给RuleFor,但RuleFor需要的是编译后的委托。
修正后的代码
以下是修复后的核心代码片段:
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)) { // 递归处理嵌套类:调用Generate()生成实例,而非直接赋值Faker对象 var nestedFakerMethod = typeof(Program) .GetMethod(nameof(AutoInferRules), BindingFlags.NonPublic | BindingFlags.Static) ?.MakeGenericMethod(property.PropertyType); var nestedFaker = nestedFakerMethod?.Invoke(null, null) as Faker; faker = faker.RuleFor(property.Name, _ => nestedFaker.Generate()); } 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())) { var elementType = property.PropertyType.GetGenericArguments()[0]; // 通过方法名精确获取GenerateList,避免依赖方法顺序 var generateListMethod = typeof(Program) .GetMethod(nameof(GenerateList), BindingFlags.NonPublic | BindingFlags.Static) ?.MakeGenericMethod(elementType); if (generateListMethod == null) continue; // 构建符合RuleFor要求的Lambda签名:(Faker f, T x) => GenerateList<ElementType>() var fakerParam = Expression.Parameter(typeof(Faker), "f"); var entityParam = Expression.Parameter(typeof(T), "x"); // 调用无参的GenerateList方法 var callExpr = Expression.Call(generateListMethod); // 编译为符合要求的委托 var lambda = Expression.Lambda<Func<Faker, T, object>>(callExpr, fakerParam, entityParam).Compile(); faker = faker.RuleFor(property.Name, lambda); } else { 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() }; }
关键修改说明
- 修复
GenerateList调用参数:移除Expression.Call中多余的参数,直接调用无参方法。 - 精确获取方法:用
nameof(GenerateList)替代Last(),确保拿到正确的方法。 - 修正Lambda签名:构建符合
RuleFor要求的Func<Faker, T, object>委托,编译后传递给RuleFor。 - 嵌套类实例生成:对嵌套类的
Faker对象调用Generate(),生成实际的实体实例而非Faker对象本身。
内容的提问来源于stack exchange,提问作者Ismail
相关产品推荐
相关产品推荐

