如何为 System.Type 创建一个 Arbitrary?
How do I create an Arbitrary for a System.Type?
我正在尝试使用 FsCheck 初始化我的模型实体。这些模型存在于 C# 中,通常通过它们的私有设置器通过 Entity Framework 进行初始化。例如(人为的):
public class Model
{
public string One { get; private set; }
public int Two { get; private set; }
}
我想创建一个 FsCheck 生成器,自动为每个 属性 使用已注册的生成器来生成模型。像这样:
let modelGenerator =
gen {
let incident = new Model()
typeof<Model>.GetProperties()
|> Array.filter (fun p -> p.CanWrite)
|> Array.iter (fun p ->
let! newVal = Arb.generateType p.PropertyType // I wish I could do this
p.SetValue(incident, newVal))
return incident
}
这有两个问题:
let!
不能在 gen
计算表达式之外使用。
Arb.generateType
不存在,我找不到方法来做它的等价物
是否可以创建一个自动在我的模型上设置私有字段的生成器?
有了反射的力量,一切皆有可能(或运行时抛出)。
module Arb =
open System.Reflection
// this is just a helper type to do reflection on.
type internal GenerateInvoker =
static member Invoke<'typ> () =
Arb.generate<'typ>
|> Gen.map box
// Invokes a generic method using a runtime type as a generic argument.
let generateType (typ: Type) =
typeof<GenerateInvoker>
.GetMethod("Invoke", BindingFlags.Static ||| BindingFlags.NonPublic)
.MakeGenericMethod([|typ|])
.Invoke(null, [||]) :?> Gen<obj>
let modelGenerator =
gen {
let incident = new Model()
let props =
typeof<Model>.GetProperties()
|> Array.filter (fun p -> p.CanWrite)
// gen builder implements For, so you can do something like this.
for prop in props do
let! newVal = Arb.generateType prop.PropertyType
prop.SetValue(incident, newVal)
return incident
}
Gen.sample 1 3 modelGenerator
我正在尝试使用 FsCheck 初始化我的模型实体。这些模型存在于 C# 中,通常通过它们的私有设置器通过 Entity Framework 进行初始化。例如(人为的):
public class Model
{
public string One { get; private set; }
public int Two { get; private set; }
}
我想创建一个 FsCheck 生成器,自动为每个 属性 使用已注册的生成器来生成模型。像这样:
let modelGenerator =
gen {
let incident = new Model()
typeof<Model>.GetProperties()
|> Array.filter (fun p -> p.CanWrite)
|> Array.iter (fun p ->
let! newVal = Arb.generateType p.PropertyType // I wish I could do this
p.SetValue(incident, newVal))
return incident
}
这有两个问题:
let!
不能在gen
计算表达式之外使用。Arb.generateType
不存在,我找不到方法来做它的等价物
是否可以创建一个自动在我的模型上设置私有字段的生成器?
有了反射的力量,一切皆有可能(或运行时抛出)。
module Arb =
open System.Reflection
// this is just a helper type to do reflection on.
type internal GenerateInvoker =
static member Invoke<'typ> () =
Arb.generate<'typ>
|> Gen.map box
// Invokes a generic method using a runtime type as a generic argument.
let generateType (typ: Type) =
typeof<GenerateInvoker>
.GetMethod("Invoke", BindingFlags.Static ||| BindingFlags.NonPublic)
.MakeGenericMethod([|typ|])
.Invoke(null, [||]) :?> Gen<obj>
let modelGenerator =
gen {
let incident = new Model()
let props =
typeof<Model>.GetProperties()
|> Array.filter (fun p -> p.CanWrite)
// gen builder implements For, so you can do something like this.
for prop in props do
let! newVal = Arb.generateType prop.PropertyType
prop.SetValue(incident, newVal)
return incident
}
Gen.sample 1 3 modelGenerator