Allow IDesignTimeDbContextFactory to be picked up via an assembly attribute
- Dominant language
- C#
- Stars
- 14.8k
- Forks
- 3.4k
- PR merge metrics
- PR metrics pending
Description
### Problem Context
F# forces a strict ordering where the last function in the last file (and files cannot reference later files either) has to be the entrypoint.
When a design time factory needs to share code with other app startup concerns this requires an awkward weaving in F#.
The outline of the code is forced to go from the simple form:
```fs
module MyApp.Program
open ...
open ...
[]
let main args =
Host.CreateDefaultBuilder().ConfigureServices(...).Build.Run()
0
```
To this 'weaved' form, given F# also requires intra-file top to bottom definitions.
```fs
namespace MyApp
open ...
open ...
module Startup =
let configureServices ... = ...
type AppDesignTimeDbContextFactory() =
interface IDesignTimeDbContextFactory with
member _.CreateDbContext(args) =
// Change some config just for design time and pull out a DbContext.
Host.CreateDefaultBuilder().ConfigureServices(configureServices).Build().ApplicationServices // etc
module Program =
[]
let main args =
Host.CreateDefaultBuilder().ConfigureServices(Startup.configureServices).Build.Run()
0
```
And `AppDesignTimeDbContextFactory` cannot just be defined inside a module because the design time code doesn't (and IMO shouldn't) scan for nested types.
### Feature Request
As a solution I propose we add an assembly attribute `DesignTimeDbContextFactoryAttribute` that the design time tooling will try to find before attempting type scanning (which should still include support for enumerating multiple definitions of the attribute by filtering down to a matching interface instantiation candidate).
Allowing the code to stay like:
```fs
module MyApp.Program
open ...
open ...
let configureServices ... = ...
type AppDesignTimeDbContextFactory() =
interface IDesignTimeDbContextFactory with
member _.CreateDbContext(args) =
// Change some config just for design time and pull out a DbContext.
Host.CreateDefaultBuilder().ConfigureServices(configureServices).Build().ApplicationServices // etc
[)>]
do ()
[]
let main args =
Host.CreateDefaultBuilder().ConfigureServices(configureServices).Build.Run()
0
```
Or alternatively:
```fs
namespace MyApp
open ...
open ...
module Program =
let configureServices ... = ...
type AppDesignTimeDbContextFactory() =
interface IDesignTimeDbContextFactory with
member _.CreateDbContext(args) =
// Change some config just for design time and pull out a DbContext.
Host.CreateDefaultBuilder().ConfigureServices(configureServices).Build().ApplicationServices // etc
[]
let main args =
Host.CreateDefaultBuilder().ConfigureServices(configureServices).Build.Run()
0
[)>]
do ()
```
Contributor guide
Assessment
This issue has not been assessed yet.