dotnet / dotnet/maui

Use top-level statements + source gen for .NET MAUI app startup/config code

Open
#2,243 1 comment 8 reactions 0 assignees View on GitHub
area-templates Task
Dominant language
C#
Stars
23.3k
Forks
2k
Avg merge
1d 14h
Merged PRs (30d)
296

Description

Consider changing .NET MAUI app startup/config code (the stuff that sets up builders, DI, fonts, services, etc.) to use top-level statements, much like ASP.NET Core apps do in .NET 6.

Imagine your app had a file such as `/MyProject/MauiProgram.cs` with this being the exact contents of the file:

```c#
var builder = MauiApp.CreateBuilder();
builder.AddThis();
builder.AddThat();

return builder.Build();
```

The default/common namespaces are all imported by the SDK and you don't need a namespace/class/method declaration. We'd use magical source generators or some other new fangled feature to detect this file and massage its contents into runnable code that can be used in the app.

This concept has come up several times, and there's even a [prototype of some aspects of this](https://github.com/dotnet/maui/blob/main/src/TestUtils/src/DeviceTests.Runners.SourceGen/RunnerGenerator.cs).

Here are some notes from the [recent PR](https://github.com/dotnet/maui/pull/2137) that sparked this again:

@mhutch said:

> This gave me an idea for using top level statements. If the body of CreateMauiApp became top level statements, a source generator could generate the CreateMauiApp method from them. My initial thought was that this would be far too magical, but AFAICT we're already using source generators to obscure the real platform-specific entrypoints, and I don't think it's any worse than that.

@redth said:

> @mhutch Yes, this would be awesome!
>
> The idea was always to source gen the Activity/AppDelegate/etc parts eventually...
>
> Last I looked at the top level statements, I don't think that source gen has access to know its namespace/type/method to be able to call it? I had thought the same once this PR was started - it would be really nice to have a top level statements file be called from the Activity/AppDelegate/etc entry points...

@mhutch said:

> IIRC the generated main method cannot be called from C#, but I assumed (maybe incorrectly) that source generators could inspect the syntax tree of top level statements like they can other code. If a source generator *can* inspect the top level statements, it can generate a new method with those same statements (and appropriate `#line` directives), and the linker can remove the unused entrypoint method. If that doesn't work, invoking the entrypoint method via reflection is a fallback option - not ideal, but a single reflection invocation is probably not a big deal - and if it is, we could have the linker optimize it into a direct call.
>
> Another aspect to consider is how we would return the user-created app object from the top level statements so the generated `CreateMauiApp` method can return it to the caller. It also needs to make sense - even if we *could* do `return app` as a top level statement, that would be kind nonsensical as there's no context as to where the app is returned *to* and what happens next.
>
> One way would be to generate a "return method" - a method the user must call on the app as the last toplevel statement. This could look like a mainloop, such as an `app.Run()` extension method, which would be cute but rather misleading about what's happening. Or we could be more explicit about what's happening e.g. `Platform.HostApp(app)`. If we used the approach of generating a `CreateMauiApp` method from the top level statements, we could directly replace the return method method call with a return statement. If we take the other approach and have the generated `CreateMauiApp` method somehow invoke the actual entrypoint method, then the return method could stash the app on a private static field from where the `CreateMauiApp` could retrieve it and return it.

Contributor guide

Open the contributing guide

Research direction

Start by reviewing MauiProgram.cs conventions, the DeviceTests.Runners.SourceGen/RunnerGenerator.cs prototype, and the platform-specific Activity/AppDelegate entry points. Determine whether a source generator can inspect top-level statements and how CreateMauiApp would receive the created app; done requires an agreed design and working startup path across supported platforms.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
desktop-dev, mobile-dev
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.