I'd let to mock an IBus with Foq.
One of the methods on the IBus is OpenPublishChannel, which returns an IPublishChannel. IPublishChannel in turn has a Bus property that returns the parent IBus.
My current code is below, but obviously it doesn't compile as mockBus is not defined by the point I need it. Is there a way of setting up recursive mocking like this without creating two mocks of either interface?
open System
open EasyNetQ
open Foq
let mockChannel =
Mock<IPublishChannel>()
.Setup(fun x -> <# x.Bus #>).Returns(mockBus)
.Create()
let mockBus =
Mock<IBus>()
.Setup(fun x -> <# x.OpenPublishChannel() #>).Returns(mockChannel)
.Create()
Foq supports a Returns : unit -> 'TValue method so you can lazily create a value.
Using a little mutation instances can refer to each other:
type IPublishChannel =
abstract Bus : IBus
and IBus =
abstract OpenPublishChannel : unit -> IPublishChannel
let mutable mockBus : IBus option = None
let mutable mockChannel : IPublishChannel option = None
mockChannel <-
Mock<IPublishChannel>()
.Setup(fun x -> <# x.Bus #>).Returns(fun () -> mockBus.Value)
.Create()
|> Some
mockBus <-
Mock<IBus>()
.Setup(fun x -> <# x.OpenPublishChannel() #>).Returns(fun () -> mockChannel.Value)
.Create()
|> Some
Related
I have the following F# function:
let myFSharpFunction : IO.TryTransform<IDatabaseService,EditForm,SyncType,ErrorDescription> =
fun _ _ -> Ok someValue
I would like to use this F# function as a value/delegate in my C# code:
FSharpFunc<IDatabaseService, FSharpFunc<EditForm, FSharpResult<SyncType, ErrorDescription>>> referenceToFSharpFunction = myFSharpFunction;
However, I get an error:
Error CS0428 Cannot convert method group 'myFSharpFunction' to
non-delegate type 'FSharpFunc>>'. Did you intend to invoke the
method?
I then tried:
public delegate FSharpResult<SyncType, ErrorDescription> myDelegate(IDatabaseService database, EditForm editForm);
...
myDelegate someDelegate = myFSharpFunction;
FSharpFunc<IDatabaseService, FSharpFunc<EditForm, FSharpResult<SyncType, ErrorDescription>>> FSharpFuncToInvoke = someDelegate;
However, this attempt also gave me an error:
type 'Sevan.Android.FormsSyncFragment.myDelegate' to
'Microsoft.FSharp.Core.FSharpFunc>>'
Update:
Attempt 1:
I then tried adding the following function to an F# module:
let toFunc2 f = Func<_, _, _> f // f : 'a -> 'b -> 'c
I next updated the C# code to the following:
var referenceToFSharpFunction = toFunc2<IDatabaseService, EditForm, FSharpResult<SyncType, ErrorDescription>>(myFSharpFunction);
But I then received this error:
Cannot convert method group 'FSharpFuncToInvoke' to non-delegate type
'FSharpFunc>>'. Did you intend to invoke
the method?
Attempt 2:
I also tried setting the F# code to the following:
let toFunc2 f = Func<IDatabaseService,EditForm, Result<SyncType,ErrorDescription>> f // f : 'a -> 'b -> 'c
Then within my C#, I attempted this:
var referenceToFSharpFunction = toFunc2<IDatabaseService, EditForm, FSharpResult<SyncType, ErrorDescription>>(myFSharpFunctione);
But that attempt gave me this error:
Error CS0308 The non-generic method
'Mock.toFunc2(FSharpFunc>>)' cannot be used with type arguments
In conclusion, how do I assign a multi-parameter F# function to a C# variable?
If you are defining some F# functionality that should be used by a C# client, then I would strongly recommend exposing all the functionality in a C#-friendly way - that means, doing all the wrapping on the F# side, so that the C# consumer does not have to worry about things like FSharpFunc at all.
It's a bit hard to say how this should work in your case - because your example does not actually show any realistic piece of code - only some kind of adapter with a fairly complex interface - but you could do something along the following lines:
// Your F# function that is used elsewhere in F# code
let myFsharpFunction =
fun _ _ -> Ok someValue
// Your F# logic, exposed as a C#-friendly `System.Func` delegate
let myCsharpFunction =
System.Func<_, _, _>(myFsharpFunction)
The F# function type FSharpFunc is something completely separate from the Func/Action used in C#, so you need to "convert" it by creating the respective type that C# understands, which is easy, but needs to be done for each number of arguments individually.
let toFunc1 f = Func<_, _> f // f : 'a -> 'b
let toFunc2 f = Func<_, _, _> f // f : 'a -> 'b -> 'c
// etc.
let toAction0 f = Action f // f : unit -> unit
let toAction1 f = Action<_> f // f : 'a -> unit
// etc.
This code snippet reproduces a problem I am having with some production code. The function containsProperty represents a real world function that is actually in a library, so that I have no say in what the signature is.
The problem is that I can't figure out how to create a wrapper function that can take a normal function as argument, and then pass that on to containsProperty. I can call containsProperty directly with a function as a lambda expression, but I can't call it with a function that comes from some other source.
The function addToGroup is the best I've come up with so far, and it uses quotations. There are two problems with that approach, which I am trying to figure out. First, how do I get rid of the Func cast in the quotation? Perhaps somehow move it into addToGroup? Second, can I build on this in order to just pass a function? I haven't succeeded in finding something that doesn't produce either a compile time error or a runtime error.
The function addToGroup2 is what I'd like to do, but it doesn't compile. The error message is "No constructors are available for the type 'Quotations.Expr<'a>'".
Why do I bother to struggle with this? Because as long as I can't treat the passed in function as a first class value, I can't create the design I'm after. I want these functions to come along from a collection of records.
If you paste this snippet into LINQPad or something, comment out addToGroup2 and the calls to it, in order to make the snippet compile and run.
open System
open System.ComponentModel
open System.ComponentModel.DataAnnotations // Reference to this assembly required.
type CfgSettings = {
mutable ConnectionString: string
mutable Port: int
}
and CfgSettingsMetadata() =
static member containsProperty<'TProperty>(propertyExpression: Linq.Expressions.Expression<Func<CfgSettings,'TProperty>>) =
Console.WriteLine "good!"
static member addToGroup f =
CfgSettingsMetadata.containsProperty(FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.QuotationToLambdaExpression f) |> ignore
static member addToGroup2 (f: CfgSettings -> 'TProperty) =
CfgSettingsMetadata.containsProperty(FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.QuotationToLambdaExpression (Quotations.Expr<Func<CfgSettings,'TProperty>>f)) |> ignore
static member BuildMetadata () =
CfgSettingsMetadata.containsProperty(fun x -> x.ConnectionString)
CfgSettingsMetadata.containsProperty(fun x -> x.Port)
CfgSettingsMetadata.addToGroup <# Func<_,_>(fun x -> x.ConnectionString) #>
CfgSettingsMetadata.addToGroup <# Func<_,_>(fun x -> x.Port) #>
CfgSettingsMetadata.addToGroup2 (fun x -> x.ConnectionString)
CfgSettingsMetadata.addToGroup2 (fun x -> x.Port)
CfgSettingsMetadata.BuildMetadata()
Both answers in question Expression<Func<T, bool>> from a F# func helped me somewhat, but I haven't found a solution yet.
So, there are two questions here.
How to pass a function without having to wrap it in <# ... #>?
For this, you just need to add the [<ReflectedDefinition>] attribute to your method's parameter. It implicitly wraps the argument passed to it in a quotation.
type CfgSettingsMetadata() =
static member addToGroup([<ReflectedDefinition>] f: Expr<CfgSettings -> 'TProperty>) =
CfgSettingsMetadata.containsProperty(LeafExpressionConverter.QuotationToLambdaExpression f) |> ignore
// Example use:
CfgSettingsMetadata.addToGroup(Func<_, _>(fun x -> x.ConnectionString))
How to convert from Expr<a -> b> to Expression<Func<a, b>>?
This is indeed explained in the question you linked, although the API has changed a bit since then.
type CfgSettingsMetadata() =
static member addToGroup ([<ReflectedDefinition>] (f: Expr<CfgSettings -> 'TProperty>)) =
let call = LeafExpressionConverter.QuotationToExpression f :?> MethodCallExpression
let lambda = call.Arguments.[0] :?> LambdaExpression
let e = Expression.Lambda<Func<CfgSettings, 'TProperty>>(lambda.Body, lambda.Parameters)
CfgSettingsMetadata.containsProperty(e) |> ignore
// Example use:
CfgSettingsMetadata.addToGroup(fun x -> x.ConnectionString)
I am reading Web cloud and mobile solution with F# and I try to follow the web site the author is building. But I have some problem, I am unable to solve. I understand the logic of what I am doing , but it looks like some piece of code is missing to make it work .I have read up to page 19.
I have the following repository module :
module Repository =
let get (source : IQueryable<_>) queryFn=
queryFn |> Seq.toList
let getAll ()=
fun s -> query { for x in s do
select x }
The idea is to use getAll in queryFn to get all items from source. But I have a cast problem between the two .
Here is the controller that makes use of it:
[<HandleError>]
type GuitarsController(context : IDisposable, ?repository ) =
inherit Controller()
let fromRepository =
match repository with
| Some v -> v
| _ -> (context :?> FsMvcAppEntities).guitars
|> Repository.get
new() = new GuitarsController(new FsMvcAppEntities())
member this.Index() =
getAll()
|> fromRepository
|> this.View
getAll() does not go well with |> fromRepository.
The type ''b -> Linq.IQueryable<'c>' is not compatible with the type
'seq<'a>'.
When looking at the type defined in the repository module I can see that queryFn is :
val get : source:IQueryable<'a> -> queryFn:seq<'b> -> 'b list
and the getall gives
unit -> s:System.Linq.IQueryable<'a> -> System.Linq.IQueryable<'a>
Your Repository.get makes no use of source :D.
Change it to:
module Repository =
let get (source : IQueryable<_>) queryFn =
queryFn source |> Seq.toList
I have the following code snippet using the reactive extensions:
let value : 't = ...
Observable.Create<'t>(fun observer ->
let subject = new BehaviorSubject<'t>(value)
let d0 = subject.Subscribe(observer)
let d1 = observable.Subscribe(subject)
new CompositeDisposable(d0, d1) :> IDisposable
)
This works. However if I drop the upcast to IDisposable then the code fails
to compile, citing ambiguous overloads. However CompositeDisposable is an
IDisposable. Why is the type inference engine failing to resolve this? Note I use this pattern almost all the time in C# returning CompositeDisposable from Observable.Create without having to upcast.
As #kvb said, functions don't support variance so upcast is required for interfaces and subclasses.
Here is a small example demonstrating the behavior with subclasses:
type A() =
member x.A = "A"
type B() =
inherit A()
member x.B = "B"
let f (g: _ -> A) = g()
let a = f (fun () -> A()) // works
let b = f (fun () -> B()) // fails
If function f is written by you, adding type constraints could help:
// This works for interface as well
let f (g: _ -> #A) = g()
let a = f (fun () -> A()) // works
let b = f (fun () -> B()) // works
Otherwise, you have to do a litle upcast as your example described.
EDIT: Since F# 6.0, auto-upcasting of interfaces and subclasses is now supported by default.
Is it possible to somehow use a pipeline to pass in the last argument of a method with tupled parameters?
An example:
// Member to call
static member Property (expr:Expr<'a -> string>, cfg:EntityInfo<'a>) = cfg.Property expr
// My curry function
let curry f x y = f (x,y)
// My EntityInfo<FileUpload>
let entityInfo = EF.Entity<FileUpload> modelBuilder
I want to be able to call it like:
entityInfo |> curry EF.Property <# fun z -> z.Path #>
instead of
EF.Property(<# fun z -> z.Path #>, entityInfo)
I believe that this is a simplified version of your problem (although you're excluding too much code to be sure):
type T() = class end
type S =
static member Method(_:int, T) = 'c'
static member Method(_:string, T) = false
let curry f x y = f(x,y)
// won't work
T() |> curry S.Method 1
As Brian mentions, overloading doesn't play nicely with type inference. In particular, since F#'s type inference works left-to-right, the compiler does not use the fact that 1 is an int when trying to do the member lookup for S.Method, which means that it can't identify the correct overload. As I see it, you have a few options:
Use distinct method names. Is there a reason that you have to use Property to refer to multiple different operations? Would it be much worse to use StringProperty, IntProperty, etc. for each overload? In general, overloading makes life harder for the compiler (and often for human maintainers, too). As an aside, I don't like the idea of naming a method Property, anyway...
Use explicit type parameters on curry, and specify them. E.g.
let curry<'a,'b,'c> f (x:'a) (y:'b) : 'c = f(x,y)
entityInfo |> curry<Expr<_ -> string>,_,_> EF.Property <# fun z -> z.Path #>
Explicitly indicate the type of EF.Property:
entityInfo |> curry (EF.Property: Expr<_ -> string> * _ -> _) <# fun z -> z.Path #>
Of course, these last two options aren't very concise, so they may defeat the purpose of using the pipelined style.
It is because it is counting entity info as an member of EF.Propery method instead of curry method, you should use
entityInfo |> curry (EF.Property) (<# fun z -> z.Path #>)