How do I get Dapper to convert data to an F# type with an option property? Simple example:
type SomeType = {
Count : int option
}
connection.QueryAsync<SomeType>(...)
This throws:
System.InvalidOperationException
A parameterless default constructor or one matching signature
(System.Int32 count) is required for SomeType materialization
Using Nullable instead of option works:
type SomeType = {
Count : Nullable<int>
}
But it's not as desirable for various reasons. For one thing, I have cases where I use string option (because F# doesn't allow null assignments normally, which is great), and Nullable<string> doesn't compile. Is there a way to configure/instruct Dapper to automatically deal with option types? I'd like to avoid using custom mappings every time.
In case it matters, using with Npgsql.
I don't think there's any support for adding handlers for open generics, so you'd have to add a type handler for each type you need.
You could define a handler like this:
type OptionHandler<'T>() =
inherit SqlMapper.TypeHandler<option<'T>>()
override __.SetValue(param, value) =
let valueOrNull =
match value with
| Some x -> box x
| None -> null
param.Value <- valueOrNull
override __.Parse value =
if isNull value || value = box DBNull.Value
then None
else Some (value :?> 'T)
And register for the types you need like this:
SqlMapper.AddTypeHandler (OptionHandler<string>())
SqlMapper.AddTypeHandler (OptionHandler<int>())
Related
My research on this seems to conclude a bug in dapper, but I'm hoppign I'm missing something simple.
I have a union type
type PrimaryKey<'x> =
| Id of int
| EmptyPrimaryKey
And I want to be able to map that to int columns in SQL.
My custom type handler is below:
type PrimaryKeyHandler<'X>() =
inherit SqlMapper.TypeHandler<PrimaryKey<'X>>()
override _.SetValue(param, value) =
printfn "Running set value"
let valueOrNull =
match value with
| PrimaryKey.Id id ->
box id
| EmptyPrimaryKey ->
null
param.Value <- valueOrNull
override _.Parse value =
if isNull value || value = box DBNull.Value
then EmptyPrimaryKey
else Id (value :?> int)
_.Parse is working correctly when I'm using Select queries, so all good there.
However when I'm trying to Insert a value, .SetValue does not seem to be being called at all and the program is dying with the type cannot be used as a parameter value
And when dumping out the values that's going into the query, it is indeed a PrimaryKey rather than an integer. And no printfn statements or breakpoints are being hit.
This doesn't seem to be a super uncommon problem but I haven't found a clear solution yet.
Can someone clarify when to use typedefof<'T> vs. typeof<'T>?
Both typedefof<System.String> and typeof<System.String> return the same Type instance.
However, they return different instances and different information for System.Collections.Generic.List<_>.
Can I think of typedefof as a new and improved typeof? Should I just switch to always using typedefof? Or is it more subtle than that?
This ought to illustrate the difference. When you use typeof, the compiler infers type arguments and constructs a concrete type. In this case, the inferred type argument is System.Object:
let t1 = typeof<System.Collections.Generic.List<_>>
let t2 = typedefof<System.Collections.Generic.List<_>>
printfn "t1 is %s" t1.FullName
printfn "t2 is %s" t2.FullName
Output:
t1 is System.Collections.Generic.List`1[[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
t2 is System.Collections.Generic.List`1
Because typeof can only return a constructed type, typedefof is necessary if you need a type object representing a generic type definition.
typeof is used when you want to get the System.Type object for a given type. typedefof is used when you want to get the System.Type that represents the type definition for a generic type. As an example that uses both, suppose you had a type called Generic<'a>, and you wanted to create a function that returned the System.Type object for the Generic of any given type.
type Generic<'a> = Value of 'a
let makeGenericOf<'a> () =
typedefof<Generic<_>>.MakeGenericType(typeof<'a>)
Here, you would use the typedefof function to get the type defintion, and typeof to get the type of 'a for constructing the generic Generic<'a> Type.
I really appreciate the answers from phoog, Aaron, and JLRishe. Here is what I have learned, based on their answers and my own experimentation.
There are two Type instances associated with generics.
There is a Type associated with a generic that has specific type parameters. For example, there is a Type associated with List<int> and a different Type associated with List<string>. This is what you get when you use typeof<>.
> typeof<List<string>>.ToString();;
val it : string = "Microsoft.FSharp.Collections.FSharpList`1[System.String]"
> typeof<List<int>>.ToString();;
val it : string = "Microsoft.FSharp.Collections.FSharpList`1[System.Int32]"
There is a Type associated with the generic type definition itself. For example, there is a single Type associated with List<'T>, which is the same for List<int>, List<string>, and List<_>. This is what you get when you use typedefof<>.
> typedefof<List<string>>.ToString();;
val it : string = "Microsoft.FSharp.Collections.FSharpList`1[T]"
> typedefof<List<int>>.ToString();;
val it : string = "Microsoft.FSharp.Collections.FSharpList`1[T]"
> typedefof<List<_>>.ToString();;
val it : string = "Microsoft.FSharp.Collections.FSharpList`1[T]"
By the way, the Type class has an instance method to GetGenericTypeDefinition(). That means, the following two return the same instance:
> Object.ReferenceEquals(typeof<List<int>>.GetGenericTypeDefinition(), typedefof<List<int>>);;
val it : bool = true
What happens if you call typeof<List<_>>? You get back the Type definition for List<Object>, as phoog mentioned.
> typeof<List<_>>.ToString();;
val it : string = "Microsoft.FSharp.Collections.FSharpList`1[System.Object]"
This is all helpful to understand. For example, suppose I need to know if an object is a generic list (of any type).
// does not give me the answer I naively expected
> o.GetType() = typeof<List<_>>;;
val it : bool = false
// does this reference point to a List<'T>?
> o.GetType().IsGenericType && o.GetType().GetGenericTypeDefinition() = typedefof<List<_>>;;
val it : bool = true
Additionally, if you want to late-bound instantiate a generic type, you can use the MakeGenericType(...) method which Aaron mentioned.
> let myList = typedefof<List<_>>.MakeGenericType(typeof<int>);;
val myList : Type = Microsoft.FSharp.Collections.FSharpList`1[System.Int32]
For the sample program:
type public MyClass(reasonForLiving:string) =
member x.ReasonForLiving with get() = reasonForLiving
let classFactory () = MyClass("up to you")
let live () =
let instance = classFactory()
if instance = null then raise(System.Exception("null is not living... that's why OO languages die from bugs"))
instance
I get the error "The type 'MyClass' does not have null as a proper value" when I go to use this class as a return value of implicitly typed functions and compare it to null (b/c of compatibility requirements with C# dependency injection I cannot rely on F# option types).
I can easily fix this by changing the null check to:
if instance :> obj = null then
However, I know ("feel") this is completely "wrong". Especially when I consider how MyClass is a reference type that shouldn't need to be boxed (speaking from a C# background).
I've read about "F# Value Restriction" and how it impacts type inference, but I can't seem to gleam how it applies to this scenario.
Q: Is there another way to do this?
Aside #1: I found a simpler method of getting the error...
type public MyClass(reasonForLiving:string) =
member x.ReasonForLiving with get() = reasonForLiving
let nullMyClass : MyClass = null
Aside #2: I did try System.Nullable without thinking... MyClass is a reference type and not a value type (struct) which Nullable<_> requires. So, just reassures me that I REALLY am dealing with a reference type and leaves me wondering why an object cast suddenly makes this work.
Update: For anyone interested, I used this as one solution for Common Service Locator with the three functions below. Each service requested must support null, so if the service class is defined in F#, you need to add the [<AllowNullLiteral>]:
let private getServiceLocator () =
try Some(Microsoft.Practices.ServiceLocation.ServiceLocator.Current)
with | _ -> None
let private getService serviceFactory =
let serviceLocator = getServiceLocator()
let service = match serviceLocator with
| None -> serviceFactory()
| _ ->
match serviceLocator.Value.GetInstance<'a>() with
| null -> serviceFactory()
| svc -> svc
match service with
| null -> None
| _ -> Some(service)
let private getRequiredService serviceFactory =
let service = getService serviceFactory
match service with
| None -> raise(MissingServiceException(""))
| _ -> service.Value
Use the [<AllowNullLiteral>] attribute:
[<AllowNullLiteral>]
type public MyClass(reasonForLiving:string) =
member x.ReasonForLiving with get() = reasonForLiving
By default, F# types do not allow null (thank heavens!). This attribute is useful for interop with other .NET languages and allows assignment/comparison with null.
The problem with the AllowNullLiteral attribute is that in addition to allowing you to compare your objects to null, it also makes it possible to set your objects to null.
Assuming that this is not desirable for your use-case, there is an easy alternative with unobservable performance impact:
let inline isNull (x:^T when ^T : not struct) = obj.ReferenceEquals (x, null)
Then rather than doing if instance = null then, do if isNull instance then instead.
This will work for any reference type (including records and DUs), but does not introduce the possibility of setting objects of your F# types to null from F# – the best of both worlds.
I know virtually nothing about F#. I don’t even know the syntax, so I can’t give examples.
It was mentioned in a comment thread that F# can declare functions that can take parameters of multiple possible types, for example a string or an integer. This would be similar to method overloads in C#:
public void Method(string str) { /* ... */ }
public void Method(int integer) { /* ... */ }
However, in CIL you cannot declare a delegate of this form. Each delegate must have a single, specific list of parameter types. Since functions in F# are first-class citizens, however, it would seem that you should be able to pass such a function around, and the only way to compile that into CIL is to use delegates.
So how does F# compile this into CIL?
This question is a little ambiguous, so I'll just ramble about what's true of F#.
In F#, methods can be overloaded, just like C#. Methods are always accessed by a qualified name of the form someObj.MethodName or someType.MethodName. There must be context which can statically resolve the overload at compile-time, just as in C#. Examples:
type T() =
member this.M(x:int) = ()
member this.M(x:string) = ()
let t = new T()
// these are all ok, just like C#
t.M(3)
t.M("foo")
let f : int -> unit = t.M
let g : string-> unit = t.M
// this fails, just like C#
let h = t.M // A unique overload for method 'M' could not be determined
// based on type information prior to this program point.
In F#, let-bound function values cannot be overloaded. So:
let foo(x:int) = ()
let foo(x:string) = () // Duplicate definition of value 'foo'
This means you can never have an "unqualified" identifier foo that has overloaded meaning. Each such name has a single unambiguous type.
Finally, the crazy case which is probably the one that prompts the question. F# can define inline functions which have "static member constraints" which can be bound to e.g. "all types T that have a member property named Bar" or whatnot. This kind of genericity cannot be encoded into CIL. Which is why the functions that leverage this feature must be inline, so that at each call site, the code specific-to-the-type-used-at-that-callsite is generated inline.
let inline crazy(x) = x.Qux(3) // elided: type syntax to constrain x to
// require a Qux member that can take an int
// suppose unrelated types U and V have such a Qux method
let u = new U()
crazy(u) // is expanded here into "u.Qux(3)" and then compiled
let v = new V()
crazy(v) // is expanded here into "v.Qux(3)" and then compiled
So this stuff is all handled by the compiler, and by the time we need to generate code, once again, we've statically resolved which specific type we're using at this callsite. The "type" of crazy is not a type that can be expressed in CIL, the F# type system just checks each callsite to ensure the necessary conditions are met and inlines the code into that callsite, a lot like how C++ templates work.
(The main purpose/justification for the crazy stuff is for overloaded math operators. Without the inline feature, the + operator, for instance, being a let-bound function type, could either "only work on ints" or "only work on floats" or whatnot. Some ML flavors (F# is a relative of OCaml) do exactly that, where e.g. the + operator only works on ints, and a separate operator, usually named +., works on floats. Whereas in F#, + is an inline function defined in the F# library that works on any type with a + operator member or any of the primitive numeric types. Inlining can also have some potential run-time performance benefits, which is also appealing for some math-y/computational domains.)
When you're writing C# and you need a function that can take multiple different parameter sets, you just create method overloads:
string f(int x)
{
return "int " + x;
}
string f(string x)
{
return "string " + x;
}
void callF()
{
Console.WriteLine(f(12));
Console.WriteLine(f("12"));
}
// there's no way to write a function like this:
void call(Func<int|string, string> func)
{
Console.WriteLine(func(12));
Console.WriteLine(func("12"));
}
The callF function is trivial, but my made-up syntax for the call function doesn't work.
When you're writing F# and you need a function that can take multiple different parameter sets, you create a discriminated union that can contain all the different parameter sets and you make a single function that takes that union:
type Either = Int of int
| String of string
let f = function Int x -> "int " + string x
| String x -> "string " + x
let callF =
printfn "%s" (f (Int 12))
printfn "%s" (f (String "12"))
let call func =
printfn "%s" (func (Int 12))
printfn "%s" (func (String "12"))
Being a single function, f can be used like any other value, so in F# we can write callF and call f, and both do the same thing.
So how does F# implement the Either type I created above? Essentially like this:
public abstract class Either
{
public class Int : Test.Either
{
internal readonly int item;
internal Int(int item);
public int Item { get; }
}
public class String : Test.Either
{
internal readonly string item;
internal String(string item);
public string Item { get; }
}
}
The signature of the call function is:
public static void call(FSharpFunc<Either, string> f);
And f looks something like this:
public static string f(Either _arg1)
{
if (_arg1 is Either.Int)
return "int " + ((Either.Int)_arg1).Item;
return "string " + ((Either.String)_arg1).Item;
}
Of course you could implement the same Either type in C# (duh!), but it's not idiomatic, which is why it wasn't the obvious answer to the previous question.
Assuming I understand the question, in F# you can define expressions which depend on the availability of members with particular signatures. For instance
let inline f x a = (^t : (member Method : ^a -> unit)(x,a))
This defines a function f which takes a value x of type ^t and a value a of type ^a where ^t has a method Method taking an ^a to unit (void in C#), and which calls that method. Because this function is defined as inline, the definition is inlined at the point of use, which is the only reason that it can be given such a type. Thus, although you can pass f as a first class function, you can only do so when the types ^t and ^a are statically known so that the method call can be statically resolved and inserted in place (and this is why the type parameters have the funny ^ sigil instead of the normal ' sigil).
Here's an example of passing f as a first-class function:
type T() =
member x.Method(i) = printfn "Method called with int: %i" i
List.iter (f (new T())) [1; 2; 3]
This runs the method Method against the three values in the list. Because f is inlined, this is basically equivalent to
List.iter ((fun (x:T) a -> x.Method(a)) (new T())) [1; 2; 3]
EDIT
Given the context that seems to have led to this question (C# - How can I “overload” a delegate?), I appear not to have addressed your real question at all. Instead, what Gabe appears to be talking about is the ease with which one can define and use discriminated unions. So the question posed on that other thread might be answered like this using F#:
type FunctionType =
| NoArgument of (unit -> unit)
| ArrayArgument of (obj[] -> unit)
let doNothing (arr:obj[]) = ()
let doSomething () = printfn "'doSomething' was called"
let mutable someFunction = ArrayArgument doNothing
someFunction <- NoArgument doSomething
//now call someFunction, regardless of what type of argument it's supposed to take
match someFunction with
| NoArgument f -> f()
| ArrayArgument f -> f [| |] // pass in empty array
At a low level, there's no CIL magic going on here; it's just that NoArgument and ArrayArgument are subclasses of FunctionType which are easy to construct and to deconstruct via pattern matching. The branches of the pattern matching expression are morally equivalent to a type test followed by property accesses, but the compiler makes sure that the cases have 100% coverage and don't overlap. You could encode the exact same operations in C# without any problem, but it would be much more verbose and the compiler wouldn't help you out with exhaustiveness checking, etc.
Also, there is nothing here which is particular to functions; F# discriminated unions make it easy to define types which have a fixed number of named alternatives, each one of which can have data of whatever type you'd like.
I'm not quite sure that understand your question correctly... F# compiler uses FSharpFunc type to represent functions. Usually in F# code you don't deal with this type directly, using fancy syntactic representation instead, but if you expose any members that returns or accepts function and use them from another language, line C# - you will see it.
So instead of using delegates - F# utilizes its special type with concrete or generic parameters.
If your question was about things like add something-i-don't-know-what-exactly-but-it-has-addition-operator then you need to use inline keyword and compiler will emit function body in the call site. #kvb's answer was describing exactly this case.
Consider my first attempt, a simple type in F# like the following:
type Test() =
inherit BaseImplementingNotifyPropertyChangedViaOnPropertyChanged()
let mutable prop: string = null
member this.Prop
with public get() = prop
and public set value =
match value with
| _ when value = prop -> ()
| _ ->
let prop = value
this.OnPropertyChanged("Prop")
Now I test this via C# (this object is being exposed to a C# project, so apparent C# semantics are desirable):
[TestMethod]
public void TaskMaster_Test()
{
var target = new FTest();
string propName = null;
target.PropertyChanged += (s, a) => propName = a.PropertyName;
target.Prop = "newString";
Assert.AreEqual("Prop", propName);
Assert.AreEqual("newString", target.Prop);
return;
}
propName is properly assigned, my F# Setter is running, but the second assert is failing because the underlying value of prop isn't changed. This sort of makes sense to me, because if I remove mutable from the prop field, no error is generated (and one should be because I'm trying to mutate the value). I think I must be missing a fundamental concept.
What's the correct way to rebind/mutate prop in the Test class so that I can pass my unit test?
As a side-note, I would probably use if .. then instead of the match construct as it makes the code more succinct (patterh matching is especially valuable when you need to test the value agains multiple complex patterns). Also, public is the default access for member, so you can make the code a bit more succinct:
type Test() =
inherit BaseImplementingNotifyPropertyChangedViaOnPropertyChanged()
let mutable prop : string = null
member this.Prop
with get() = prop
and set(value) =
if value <> prop then
prop <- value
this.OnPropertyChanged("Prop")
Try this:
type Test() =
inherit BaseImplementingNotifyPropertyChangedViaOnPropertyChanged()
let mutable prop: string = null
member this.Prop
with public get() = prop
and public set value =
match value with
| _ when value = prop -> ()
| _ ->
prop <- value
this.OnPropertyChanged("Prop")
You need to make the binding mutable and then alter its value in your setter. In your initial code, you were just creating a new binding (also called prop) within your setter, so no change was visible.
In your pattern match you are actually binding a new value with
let prop = value
When you bind a value like this with the same name, it will shadow the other value for the scope of the newly declared one. I believe what you actually want to do is this:
prop <- value