We're working on making ASP.NET Core and EntityFramework work with trimming and ahead of time compilation (.NET NativeAOT). One of the big challenges is moving away from dynamic runtime code generation. Let's talk about what that means👇🏾 #dotnet #aspnetcore
Why do we care about trimming and NativeAOT? Faster startup and smaller output. This is useful for reducing the size of your output, which can be impactful for things like smaller container images.
When you type write a minimal API, the framework will look at the method signature you pass and generate the appropriate code to pass the expected parameters and process the response. The two examples below are mostly equivalent.
Today this is done by generating code at runtime since we have features that depend in runtime knowledge in order to generate code. As an example, when you have a registered service in the DI container then we can detect that and generate service resolution code.
Pivoting away from runtime code generation for a minute, C# has source generators, which allows anyone to write a library that analyses code statically and generate more code. In theory it should be possible to use this to replace some pieces of runtime code generation.
Source generators work well today when there is a natural declaration site. What do I mean by that? Well look at the hello world for source generators:
There's a partial method that is "filled in" with generated code. That pattern works really well when there's a natural place to declare a method or class, otherwise, it tends to lead a slightly awkward user experience. devblogs.microsoft.com/dotnet/regular…
For minimal APIs, we want to generate code based on the user typed and then somehow, use that code at runtime. The user didn't need to write any partial classes or methods, they just turned on the source generator and got this for free. Can we have our cake and eat it too?
We have to solve 2 problems:
1. We need to generate code based on each unique call to MapGet/Put/Post/etc method and we need to be able to identify this generated code at runtime.

2. We need to somehow tell the Map* to use this generated code instead of the runtime code gen.
What cache key can we use to uniquely identify a call to Map? Maybe the method name "MapGet" and the route? That would mean that we can statically determine the entire route at compile time, possible but there are problems when you introduce things like route groups.
Remember we need something that we can determine at compile time that can be retrieved at runtime. What about the file name and line number? It's not perfect but it works well. While running the source generator, we can generate code based on the line and file path.
At runtime you can use the [CallerLineNumber] and [CallerFilePath] attributes to get this data in any method learn.microsoft.com/en-us/dotnet/a…. What happens if you have 2 methods on the same line?
OK we solved the first problem, now what about the second one? How do we trick the compiler into calling our method instead of the one the user originally generated? By generating more specific method overloads!
ASP.NET Core has overloads for app.Map{Verb} that are weakly typed. We can generate overloads that take a strongly typed delegate that will "win" overload resolution and let us wire up the source generated code.
And here's the prototype:
Original code - github.com/davidfowl/uCon…
Generated code - github.com/davidfowl/uCon…
I showed this to @jaredpar today and got this look:
This is one of my finest hacks yet:

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with David Fowler 🇧🇧🇺🇸

David Fowler 🇧🇧🇺🇸 Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @davidfowl

Sep 22
OK C# coding challenge from today's discussion. This came up today in the context of "async and concurrency is *HARD* even for very experienced developers". I will share some techniques after seeing some answers. #dotnet #csharp
First version is using a CancellationToken
Using new primitives in .NET 6 this was one of the cleanest I could come up with:
Read 4 tweets
Sep 20
Declarative VS imperative, which do you prefer and why? #dotnet #aspnetcore ImageImage
What about now? ImageImage
I don't think one of these is better than the other, but to show how removing indirection can make the understanding of what the code is doing simpler: ImageImage
Read 4 tweets
Jul 8
Here’s another “auth is hard in .NET” thread reddit.com/r/dotnet/comme… #dotnet #aspnetcore
To help the team contextualize why it is hard outside of the domain itself being hard, it would be great to see some code samples. Samples from other frameworks that are runnable. Most of these threads conflate everything under the auth banner and require 20 questions understand
the problem. It’s fine to rant but we want to make real improvements. After the rant please show the code. We need to understand the scenario, the exact scenario. Sharing code leaves less room for ambiguity.
Read 10 tweets
Jun 27
COVID will be “over” when people stop posting tests results on Twitter. It’s not “normal” or “endemic” yet socially. It feels pretty inevitable at this point, there’s still a guilt associated with having it (you could have spread it unknowingly).
It’ll be “like the flu” and “normalized” socially when people stop doing that. So, IMHO Covid isn’t “over” yet…
As an example of what this “new normal” feels like: Hanging out with people and then waiting for 3-5 days to pass to see if you have any symptoms. Knowing you have to travel in a week and trying to reduce the possibility of getting it by reducing too much human infraction before.
Read 5 tweets
Jun 27
This thread was good because it helped clarify my thinking. There are 2 phases (for simplicity) where ClaimsPrincipal shows up:
- The authentication flow
- The authorization flow

Claims are typically used to store authentication data. #dotnet #aspnetcore 🧵👇🏾
That data is then used to look up more user information (profile data) usually store in a database/cache. This profile data usually also contains permissions and authorization rules are then run over this user for different types of application "resources".
These resources typically include (but are not restricted to):
- The HTTP endpoint
- Some business object

The authorization process usually needs access to all user profile information including permissions to do authorization checks.
Read 11 tweets
Jun 26
The oral history of Dave Cutler is a real gem:
Part 1:
Part 2:
Windows NT is a marvel of an operating system and his work has been immensely impactful on the industry at large. I also love that he's an engineer through and through.
Some gems:
- Engineers should care *deeply* about the quality of the code they write (he hated when he had bugs assigned to him).
- Coding != Software engineering. They brought strong engineering culture to Microsoft from DEC.
- Go interview elsewhere to know your worth😉.
Watching these luminaries, I see a pattern of small teams of highly capable people building largely impactful software projects.
Read 4 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Don't want to be a Premium member but still want to support us?

Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal

Or Donate anonymously using crypto!

Ethereum

0xfe58350B80634f60Fa6Dc149a72b4DFbc17D341E copy

Bitcoin

3ATGMxNzCUFzxpMCHL5sWSt4DVtS8UqXpi copy

Thank you for your support!

Follow Us on Twitter!

:(