You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Bogus反射生成假数据时动态表达式参数数量错误求助

问题原因及解决方法

直接报错原因

你在构建表达式调用GenerateList<T>时,错误地传递了一个额外参数(Expression.New(generateListMethod!.ReturnType)),但GenerateList<T>是无参静态方法,参数数量不匹配直接触发了报错。

除此之外,代码还有几处逻辑问题需要修正:

其他问题点

  1. 获取GenerateList方法的方式不可靠:用GetMethods().Last()依赖方法定义顺序,容易拿到错误方法,应该通过方法名精确获取。
  2. Lambda表达式类型不匹配:Bogus的RuleFor要求第二个参数是Func<Faker, T, TProperty>类型委托,但你定义的Expression.Lambda<Func<T, List<T>>>不符合这个签名。
  3. 嵌套类赋值错误:直接把Faker<T>对象赋值给属性,而不是调用Generate()方法生成实例。
  4. 传递表达式对象而非委托:把未编译的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() };
}

关键修改说明

  1. 修复GenerateList调用参数:移除Expression.Call中多余的参数,直接调用无参方法。
  2. 精确获取方法:用nameof(GenerateList)替代Last(),确保拿到正确的方法。
  3. 修正Lambda签名:构建符合RuleFor要求的Func<Faker, T, object>委托,编译后传递给RuleFor。
  4. 嵌套类实例生成:对嵌套类的Faker对象调用Generate(),生成实际的实体实例而非Faker对象本身。

内容的提问来源于stack exchange,提问作者Ismail

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 03:57:04