I am re-writing a C# ASP.NET Web API application in F#. I have Models and Controllers done and I moved onto MyDependencyResolver that implements IDependencyResolver.
I am having a problem implementing the GetService method, whose signature in C# is:
object GetService(System.Type serviceType)
So I need to return an obj and take a System.Type as a parameter.
This is what I have so far in F#:
type MyDependencyResolver() =
interface System.Web.Http.Dependencies.IDependencyResolver with
member this.BeginScope() : IDependencyScope =
this :> IDependencyScope
member this.GetService(serviceType:Type) : obj =
if (serviceType = typeof<Controllers.HomeController>) then
let homeController = new Controllers.HomeController(arg1, arg2, arg3, arg4)
homeController :> obj
// ???
elif (serviceType = typeof<_>) then
null
member this.GetServices (serviceType: Type) :IEnumerable<obj> =
let x = new List<obj>()
x :> IEnumerable<obj>
member this.Dispose() =
()
So if serviceType is of type HomeController I want to return an instance of HomeController, and if it's of any other type I want to return null. How do I do that in F#?
Edit:
GetService method in C#:
public object GetService(Type serviceType)
{
if (serviceType == typeof(Controllers.HomeController)){
return new Controllers.HomeController(arg1, arg2, arg3, arg4);
}
return null;
}
You could just use Activator.CreateInstance(serviceType) but where do you get the constructor arguments from?
In my projects I use Unity, which is configured as follows:
let private ConfigureUnity (config : HttpConfiguration) =
let rec unityResolver (container : IUnityContainer) =
{ new IDependencyResolver with
member this.BeginScope() =
unityResolver(container.CreateChildContainer()) :> IDependencyScope
member this.GetService serviceType =
try container.Resolve(serviceType) with
| :? ResolutionFailedException -> null
member this.GetServices serviceType =
try container.ResolveAll(serviceType) with
| :? ResolutionFailedException -> Seq.empty
member this.Dispose() = container.Dispose()
}
config.DependencyResolver <- (new UnityContainer())
.RegisterType<IFoo, FooImplementation>(new HierarchicalLifetimeManager())
.RegisterType<IBar, BarImplementation>(new HierarchicalLifetimeManager())
|> unityResolver
Classes (such as your controllers) are then resolved automatically and Unity will create dependencies (the constructor arguments) for you. Using other dependency injection frameworks should be straightforward.
Related
I want to return an HttpResponseMessage, which implements IDisposable, within a Result (or any other discriminated union). However, since Result itself is not IDisposable, I can't use! it like I would for the disposable object itself. What do I do? Can I implement my own DU called DisposableResult that implements IDisposable itself?
Below is an example of what I mean. crawlStuff asynchronously returns Result<HttpResponseMessage, string>. I can't use! the result, leading to a memory leak unless I manually release it.
open System.Net.Http
let crawlStuff (client : HttpClient) : Async<Result<HttpResponseMessage, string>> =
async {
// res is HttpResponseMessage which implements IDisposable
let! res = client.GetAsync("https://ifconfig.me") |> Async.AwaitTask
return
if res.IsSuccessStatusCode then
Ok res
else
Error "Something wrong"
}
async {
use client = new HttpClient()
// Memory leak because result it could carry HttpResponseMessage.
// I want to use! here, but can't because Result<> is not IDisposable
let! response = crawlStuff client
printfn "%A" response
} |> Async.RunSynchronously
Yes, you can implement your own disposable result type, like this:
type DisposableResult<'t, 'terr when 't :> IDisposable> =
| DOk of 't
| DError of 'terr
interface IDisposable with
member this.Dispose() =
match this with
| DOk value -> value.Dispose()
| _ -> ()
Usage would then be:
open System.Net.Http
let crawlStuff (client : HttpClient) : Async<Result<HttpResponseMessage, string>> =
async {
// res is HttpResponseMessage which implements IDisposable
let! res = client.GetAsync("https://ifconfig.me") |> Async.AwaitTask
return
if res.IsSuccessStatusCode then
DOk res
else
DError "Something wrong"
}
async {
use client = new HttpClient()
use! response = crawlStuff client
printfn "%A" response
} |> Async.RunSynchronously
I would've create wrapper around Result, that will dispose underlying values:
let (|AsDisposable|) x =
match box x with
| :? IDisposable as dis -> ValueSome dis
| _ -> ValueNone
type ResultDisposer<'v, 'e> =
struct
val Result : Result<'v, 'e>
new res = { Result = res }
interface IDisposable with
member r.Dispose() =
match r.Result with
// | Ok (:? IDisposable as dis) // causes FS0008, so we have to hack
| Ok (AsDisposable (ValueSome dis))
| Error (AsDisposable (ValueSome dis)) -> dis.Dispose()
| _ -> ()
end
type Result<'a, 'b> with
member r.AsDisposable = new ResultDisposer<'a, 'b>(r)
And use it this way
async {
use client = new HttpClient()
let! response = crawlStuff client
use _ = response.AsDisposable
printfn "%A" response
} |> Async.RunSynchronously
This solution avoids need to rewrite existing code to DisposableResult and avoids allocations when disposable value is reference type, like in case of HttpResponseMessage. But decompilation shows that F# boxes ResultDisposer, even though it shouldn't :(
I have two types coming from a C# lib:
one is defined like this (only signatures):
public class CallResult<T>: CallResult
{
public CallResult([AllowNull]T data, Error? error): base(error)
public static implicit operator bool(CallResult<T> obj)
public bool GetResultOrError([MaybeNullWhen(false)] out T data, [NotNullWhen(false)] out Error? error)
public new static WebCallResult<T> CreateErrorResult(Error error)
}
and the second one derives from it:
public class WebCallResult<T>: CallResult<T>
{
public HttpStatusCode? ResponseStatusCode { get; set; }
public IEnumerable<KeyValuePair<string, IEnumerable<string>>>? ResponseHeaders { get; set; }
public WebCallResult(HttpStatusCode? code, IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders, [AllowNull] T data, Error? error): base(data, error)
public WebCallResult(WebCallResult<T> callResult): base(callResult.Data, callResult.Error)
public static WebCallResult<T> CreateFrom<Y>(WebCallResult<Y> source) where Y : T
public static WebCallResult<T> CreateErrorResult(HttpStatusCode? code, IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders, Error error)
}
and they both come from:
public class CallResult
{
public Error? Error { get; internal set; }
public bool Success => Error == null;
public CallResult(Error? error)
public static implicit operator bool(CallResult obj)
public static WebCallResult CreateErrorResult(Error error)
}
Some api calls return a CallResult, others return a WebCallResult.
Right now I use two times the same code to handle it:
// turn a webcall result into a Result object
let processResultWeb (applyOnOk: 'a -> 'b) (result: WebCallResult<'a>) =
match result.Success with
| true -> Result.Ok (applyOnOk result.Data)
| false -> Result.Error (decodeError result.Error)
// turn a webcall result into a Result object
let processResult (applyOnOk: 'a -> 'b) (result: CallResult<'a>) =
match result.Success with
| true -> Result.Ok (applyOnOk result.Data)
| false -> Result.Error (decodeError result.Error)
Which doesn't really make sense since it's the same code and I'm only caring about the data from the base class (CallResult).
So I would like to cast both types to the base class:
let a: WebCallResult = ...
let r = a :> CallResult
but this results in a compiler error:
[FS0001] The type 'CallResult' is not compatible with the type 'WebCallResult<'a>'
how can I check the result for both types by just accessing the fields from their base class, but using the same generic type.
Edit:
the source code of the classes is here: https://pastebin.com/mrw5W7xk
The issue is that I want to go from:
WebCallResult<'a'> to CallResult<'a>
and the generic seems to be the issue.
Using your code, I'm able to cast with no problem, even with generics. Here's an example:
let foo x =
WebCallResult<_>(System.Nullable(), Array.empty, x, Error())
let a : WebCallResult<int> = foo 3
let r = a :> CallResult<_>
let b : WebCallResult<string> = foo "str"
let q = b :> CallResult<_>
I am trying to override a method provided by an interface/API and have to assign a new value to one of the method's argument. If I try to assign to the passed argument, it'll give an error.
override _.Emit(eventInfo:SequenceStartEventInfo, emitter:IEmitter) =
eventInfo <- SequenceStartEventInfo(eventInfo.Source)
[...]
I am looking for behavior matching the following C# code:
public override void Emit(SequenceStartEventInfo eventInfo, IEmitter emitter) {
eventInfo = new SequenceStartEventInfo(eventInfo.Source)
...
}
If I change it and try to pass by reference (eventInfo:byref<SequenceStartEventInfo>) then it'll no longer match the available overloads.
The F# language reference on parameters and methods doesn't provide any help when dealing with this specific case. What is the best way to handle this Scenario?
In C# you can assign a new value to the argument variable, but as it is not passed by reference, this won't change the variable of the caller (even though the passed object is a reference type):
public static void Main()
{
var rt = new RefType { Value = 3 };
Change(rt);
Console.WriteLine(rt.Value); // still 3
}
public class RefType {
public int Value { get; set; }
}
public static void Change(RefType notByRef){
notByRef = new RefType { Value = 42 };
}
the F# equivalent (where parameters are immutable) would be shadowing:
type RefType() =
member val Value = 0 with get, set
let Change notByRef =
let notByRef = RefType(Value = 42);
// now, `notByRef` hides the method parameter
()
let [<EntryPoint>] Main _ =
let rt = RefType(Value = 3);
Change(rt);
printfn "%i" rt.Value // still 3
0
I have an interface in F# (generated from some typescript) that looks like this:
type [<AllowNullLiteral>] AppOptions =
abstract credential: Admin.Credential.Credential option with get, set
abstract databaseAuthVariableOverride: Object option with get, set
abstract databaseURL: string option with get, set
abstract storageBucket: string option with get, set
abstract projectId: string option with get, set
I thought that the easiest way to create an instance of that type would be to create a simple object expression, but I can't get it to work. Isn't member val allowed in object expression? If not, what is the easiest way to create a simple instance of an interface with getters and setters on all properties? This is what I tried that didn't work:
let options =
{ new Admin.AppOptions with
member val credential: Admin.Credential.Credential option = None with get, set
member val databaseAuthVariableOverride: obj option = None with get, set
member val databaseURL: string option = None with get, set
member val databaseURL: string option = None with get, set
member val projectId: string option = None with get, set
}
I dont think member var is in the object expression spec only the long form properties like this are allowed:
let options =
let mutable credential = None
let mutable databaseAuthVariableOverride = None
let mutable databaseURL = None
let mutable storageBucket = None
let mutable projectId = None
{ new AppOptions with
member x.credential with get() = credential and set v = credential <- v
member x.databaseAuthVariableOverride with get() = databaseAuthVariableOverride and set v = databaseAuthVariableOverride <- v
member x.databaseURL with get() = databaseURL and set v = databaseURL <- v
member x.storageBucket with get() = storageBucket and set v = storageBucket <- v
member x.projectId with get() = projectId and set v = projectId <- v
}
Which would project C# like code by the compiler like this:
[assembly: FSharpInterfaceDataVersion(2, 0, 0)]
[assembly: AssemblyVersion("0.0.0.0")]
[CompilationMapping(SourceConstructFlags.Module)]
public static class _
{
[Serializable]
[AllowNullLiteral]
[CompilationMapping(SourceConstructFlags.ObjectType)]
public interface AppOptions
{
override FSharpOption<object> credential
{
get;
set;
}
override FSharpOption<object> databaseAuthVariableOverride
{
get;
set;
}
override FSharpOption<string> databaseURL
{
get;
set;
}
override FSharpOption<string> storageBucket
{
get;
set;
}
override FSharpOption<string> projectId
{
get;
set;
}
}
See sharplab
A normal type is probably more succinct here:
type t() =
interface AppOptions with
member val credential = None with get, set
member val databaseAuthVariableOverride = None with get, set
member val databaseURL = None with get, set
member val storageBucket = None with get, set
member val projectId = None with get, set
What Im trying to do is create a provided type that calls its base constructor like this in C#:
public class SubclassController : BaseClass
{
public SubclassController (IntPtr handle) : base (handle)
{}
}
The closest I can currently get is this:
public sealed class SubclassController : BaseClass
{
public SubclassController (IntPtr handle)
{
this;
base..ctor (handle);
}
Which although having the same functionality is not entirely the same.
The code I am using to build the ProvidedConstructor is as follows:
let providedConstructor = ProvidedConstructor([ProvidedParameter("handle", typeof<IntPtr>)])
let ctorInfo = typeof<SubclassController>.GetConstructor(BindingFlags.Public ||| BindingFlags.Instance, null, [|typeof<IntPtr>|], null)
providedConstructor.BaseConstructorCall <- fun args -> ctorInfo, args
providedConstructor.InvokeCode <- fun args -> <## () ##>
It was actually a bug in ProvidedTypes.fs which has now been fixed in the latest version. It is available from the usual place at codeplex thanks to #desco
So this code is actually all thats needed for a correctly formed base constructor call:
let providedConstructor = ProvidedConstructor([ProvidedParameter("handle", typeof<IntPtr>)])
let ctorInfo = typeof<SubclassController>.GetConstructor(BindingFlags.Public ||| BindingFlags.Instance, null, [|typeof<IntPtr>|], null)
providedConstructor.BaseConstructorCall <- fun args -> ctorInfo, args
providedConstructor.InvokeCode <- fun args -> <## () ##>