Имитация динамических свойств в выражении для использования с Bogus

Я хочу настроить правило Bogus, которое задает свойство dynamic для простой в остальном модели.

Н.Б. Я знаю, что это очень сильно связано с компилятором/средой выполнения С# в целом и очень приветствовало бы решение в этом контексте. Тем не менее, я также был бы признателен за конкретное решение Bogus, если таковое имеется.

public class Foo
{
    public string Id { get; set; }
    public dynamic Attributes { get; set; }
}

Используя библиотеку Bogus, я хочу настроить правило Faker, например:

public static IReadOnlyCollection<Foo> FakeFoos(int amount)
{
    var config = new Faker<Foo>()
        .StrictMode(false)
        .RuleFor(x => x.Id, y => y.Random.Guid().ToString("N"))
        .RuleFor(x => x.Attributes.......)  // <-- this here
    return config.Generate(amount);
}

Скажем так, я хочу установить foo.Attributes.Percentage в целое число. Я пробовал несколько способов, и все они приводили к разным ошибкам на dotnetcore 3.1.

Пример 1:

// Error [CS1963] An expression tree may not contain a dynamic operation
.RuleFor(x => x.Attributes.Percentage, y => y.Random.Int(70, 90))

Пример 2:

// Error System.ArgumentException : Your expression '(x.Attributes As SomeWrappingClass).Percentage' cant be used. 
// Nested accessors like 'o => o.NestedO...
.RuleFor(x => (x.Attributes as SomeWrappingClass).Percentage, y => y.Random.Int(70, 90))

Пример 3:

// Error RuntimeBinderException : Cannot perform runtime binding on a null reference
.RuleFor(x => x.Attributes, y => new SomeWrappingClass
{
    Percentage = y.Random.Int(70, 90),
});

У кого-нибудь есть идея или предложение как установить динамические свойства в этом случае?


person Juliën    schedule 12.05.2020    source источник


Ответы (1)


Во-первых, спасибо за использование Подделка!

Используя следующий код:

void Main()
{
   var foo = FakeFoos(1).First();
   foo.Dump();
   Console.WriteLine($"Percentage: {foo.Attributes.Percentage}");
}

Вариант 1 — анонимный тип

Самым элегантным способом использования dynamic было бы использование анонимного типа:

public static IReadOnlyCollection<Foo> FakeFoos(int amount)
{
   var config = new Faker<Foo>()
       .StrictMode(false)
       .RuleFor(x => x.Id, y => y.Random.Guid().ToString("N"))
       .RuleFor(x => x.Attributes, y => new { Percentage = y.Random.Int(70, 90) });
   return config.Generate(amount);
}

введите здесь описание изображения


Вариант 2 - ExpandoObject

Более традиционно, используя ExpandoObject:

public static IReadOnlyCollection<Foo> FakeFoos(int amount)
{
   var config = new Faker<Foo>()
       .StrictMode(false)
       .RuleFor(x => x.Id, y => y.Random.Guid().ToString("N"))
       .RuleFor(x => x.Attributes, y =>
            {
               dynamic eo = new ExpandoObject();
               eo.Percentage = y.Random.Int(70, 90);
               return eo;
            });
   return config.Generate(amount);
}

введите здесь описание изображения


Надеюсь, что это поможет, дайте мне знать, если у вас есть еще вопросы. :)

person Brian Chavez    schedule 19.05.2020