SaturnFramework / Saturn

Opinionated, web development framework for F# which implements the server-side, functional MVC pattern
https://saturnframework.org
MIT License
715 stars 109 forks source link

Suggestion on Dependency Injection in Saturn #275

Closed Arshia001 closed 3 years ago

Arshia001 commented 3 years ago

To access services in Giraffe, the documentation says to get them through the HttpContext. This is essentially the equivalent of transitioning from the very powerful dependency injection pattern to the service locator anti-pattern.

Since Saturn is here to fix Giraffe's wrong choices, I was hoping for a better DI solution in Saturn. A search reveals that one can use DI in controller workflows by using the add/show/etc. overloads which provide an additional dependency argument, but even that only works for one dependency AFAIK.

In the world of Saturn, I think this is how a good DI solution would look:

let someController (dep1: IDependency, dep2: IOtherDependency) = controller {
    ...
}

let someRouter (dep: IYetAnotherOne) = router {
    get "/getMyText" (text dep.SomeText) // dependencies now easily accessible, even without access to HttpContext
    forward "/path" someController // The dependencies will be automatically resolved, I'll explain how this works below
}

To make this work, for any CE builder method that accepts an HttpHandler, we would add a new overload of the form 'Dependencies -> HttpHandler. Whenever an HttpHandler must be called, an HttpContext is readily available, which we will use to resolve the services.

If this approach seems acceptable in principle, I'm more than happy to contribute the implementation.