Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Testing 如何为System.Type创建任意类型?_Testing_F#_Fscheck - Fatal编程技术网

Testing 如何为System.Type创建任意类型?

Testing 如何为System.Type创建任意类型?,testing,f#,fscheck,Testing,F#,Fscheck,我正在尝试使用FsCheck初始化模型实体。这些模型生活在C#中,通常通过其私有setter通过实体框架进行初始化。例如(人为的): 我想创建一个FsCheck生成器,它自动为每个属性使用注册的生成器来生成模型。大概是这样的: let modelGenerator = gen { let incident = new Model() typeof<Model>.GetProperties() |> Array.f

我正在尝试使用FsCheck初始化模型实体。这些模型生活在C#中,通常通过其私有setter通过实体框架进行初始化。例如(人为的):

我想创建一个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 modelGenerator=
根{
让事件=新模型()
typeof.GetProperties()
|>Array.filter(fun p->p.CanWrite)
|>Array.iter(乐趣p->
let!newVal=Arb.generateType p.PropertyType//我希望我能这样做
p、 设置值(事件,新值))
返回事件
}
这有两个问题:

  • let不能在
    gen
    计算表达式之外使用
  • Arb.generateType
    不存在,我也找不到一种方法来实现它的等效功能

  • 有没有可能创建一个生成器来自动设置我的模型上的私有字段?

    有了反射功能,一切都是可能的(或者在运行时抛出)

    模块Arb=
    开放系统。反射
    //这只是一个要进行反射的助手类型。
    类型内部GenerateInvoker=
    静态成员调用
    |>通用地图盒
    //使用运行时类型作为泛型参数调用泛型方法。
    let generateType(类型:Type)=
    类型
    .GetMethod(“调用”,BindingFlags.Static | | | BindingFlags.NonPublic)
    .MakeGenericMethod([|类型]
    .Invoke(null,[| |]):?>Gen
    让modelGenerator=
    根{
    让事件=新模型()
    让道具=
    typeof.GetProperties()
    |>Array.filter(fun p->p.CanWrite)
    //gen builder实现了,所以您可以这样做。
    对于道具中的道具呢
    let!newVal=Arb.generateType prop.PropertyType
    属性设置值(事件,新值)
    返回事件
    }
    Gen.sample 1 3模型生成器
    
    在我向GetMethod调用添加绑定标志后效果非常好:
    typeof.GetMethod(“Invoke”,BindingFlags.Static | | | BindingFlags.NonPublic)
    @Daws:对,我可能在测试后对答案做了太多的修改。
    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
        }
    
    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