← Back to all projects

LEARN DOTNET CORE DEEP DIVE

Project 7: Cross-Platform Process Manager (CLI Tool)

  • File: LEARN_DOTNET_CORE_DEEP_DIVE.md
  • Main Programming Language: C#
  • Alternative Programming Languages: Go
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: System / OS Interaction
  • Software or Tool: System.Diagnostics.Process, System.CommandLine
  • Main Book: “.NET Core in Action” by Dustin Metzgar

What you’ll build: A top-like CLI tool that lists running processes, tracks their CPU/Memory usage over time, and can kill/restart them. It must work identically on macOS, Linux, and Windows.

Why it teaches OS Interaction: .NET is cross-platform, but OSs are not. You will face the challenge of different line endings, different signal handling (SIGTERM vs taskkill), and different file system permissions. You will learn System.Diagnostics and how to build rich CLI UIs (using Spectre.Console).

Core challenges you’ll face:

  • Cross-Platform Differences: Windows uses Handles; Linux uses PIDs/Signals. How do you abstract this? (maps to: Runtime Information).
  • Process Lifecycle: Handling Exited events and managing child processes.
  • Console UI: Updating the screen without flickering (ANSI escape codes).

Key Concepts:

  • System.Diagnostics: Process management APIs.
  • RuntimeInformation: Checking IsOSPlatform(OSPlatform.Linux).
  • ANSI/VT100 Codes: Controlling the terminal cursor.

Difficulty: Intermediate Time estimate: Weekend Prerequisites: Basic C#.


Real World Outcome

You’ll have a task manager in your terminal.

Example Output:

$ dotnet run -- monitor --refresh 1s
[Process Monitor - Linux x64]
PID    NAME         CPU%   MEM(MB)
----------------------------------
1402   dotnet       2.5    140
8912   chrome       1.1    450
...
[Press K to Kill, Q to Quit]

The Core Question You’re Answering

“How does .NET talk to the underlying Operating System?”

It uses P/Invoke internally, but exposes a nice abstraction (Process). However, abstractions leak. You’ll find out where.

Concepts You Must Understand First

Stop and research these before coding:

  1. Process vs Thread
    • What is the difference? Which one owns memory?
    • Resource: “Operating Systems: Three Easy Pieces” (Process Virtualization).
  2. Signals
    • What happens when you press Ctrl+C?
    • Resource: Unix Signals documentation.

Questions to Guide Your Design

Before implementing, think through these:

  1. Polling: How do you calculate CPU usage? (Hint: Delta of TotalProcessorTime / Delta of WallClockTime).
  2. Permissions: Why does your tool crash when trying to inspect a root/admin process?

Thinking Exercise

The Math of CPU Usage

If a process used 100ms of CPU time in a 1000ms window, and you have 4 cores, what is the CPU usage percentage? (100 / 1000) / 4 = 2.5%? Or 25% of one core? (Task Manager conventions vary).

The Interview Questions They’ll Ask

Prepare to answer these:

  1. “How do you handle AppDomain.CurrentDomain.ProcessExit?”
  2. “What is a ‘Zombie Process’?”
  3. “Why is Process.Start() dangerous if arguments aren’t escaped?”

Hints in Layers

Hint 1: Libraries Use Spectre.Console for the UI. It handles the drawing loop nicely.

Hint 2: Diagnostics Process.GetProcesses() is expensive. Don’t call it every 10ms.

Hint 3: Calculating CPU Store (DateTime Time, TimeSpan Cpu) for each PID. On next tick, (NewCpu - OldCpu) / (NewTime - OldTime).

Books That Will Help

Topic Book Chapter
CLI Apps “.NET Core in Action” Ch. 4
OS Concepts “Operating Systems: Three Easy Pieces” Part 1

Project 8: Middleware Pipeline & Request Processing

  • File: LEARN_DOTNET_CORE_DEEP_DIVE.md
  • Main Programming Language: C#
  • Alternative Programming Languages: JS (Express)
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 4. The “Open Core” Infrastructure
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Web Architecture
  • Software or Tool: ASP.NET Core (Conceptual)
  • Main Book: “ASP.NET Core in Action” by Andrew Lock

What you’ll build: A request processing pipeline. You will define a HttpContext class and a RequestDelegate delegate. You will implement a PipelineBuilder that allows chaining “Middleware” (Functions) using .Use(). One middleware will log, one will handle errors, one will route.

Why it teaches Web Architecture: This is how ASP.NET Core works. It’s not a monolithic server; it’s a chain of functions. app.UseMvc() is just one link in the chain. Building this makes you understand “short-circuiting” and “exception handling middleware.”

Core challenges you’ll face:

  • The Delegate Chain: Understanding Func<RequestDelegate, RequestDelegate>.
  • Async Recursion: The “onion architecture” (Doing work before and after the next component).
  • Error Propagation: Catching exceptions from downstream middleware.

Key Concepts:

  • Chain of Responsibility: Design Pattern.
  • Middleware: Invoke(HttpContext context, Func<Task> next).
  • Short-Circuiting: Returning without calling next().

Difficulty: Intermediate Time estimate: Weekend Prerequisites: Delegates, Async/Await.


Real World Outcome

You’ll see requests flow through layers.

Example Output:

$ dotnet run -- pipeline-demo
[Logger Middleware] Request started for /api/test
  [Auth Middleware] Checking token... Valid.
    [Endpoint Middleware] Handling request... 200 OK.
  [Auth Middleware] Finished.
[Logger Middleware] Request finished in 5ms.

The Core Question You’re Answering

“What does app.Use() actually do?”

It wraps the previous delegate in a new delegate. It builds a Russian nesting doll of functions.

Concepts You Must Understand First

Stop and research these before coding:

  1. Delegates
    • What is Func<T, T>?
    • Resource: C# Language Specification.
  2. The Pipeline Pattern
    • How does the “Chain of Responsibility” pattern work?
    • Resource: Gang of Four Design Patterns.

Questions to Guide Your Design

Before implementing, think through these:

  1. Builder: You need a List<Func<RequestDelegate, RequestDelegate>>.
  2. Build(): You iterate the list in reverse to wrap the functions. Why reverse?

Thinking Exercise

The Wrapper

If I have:

app.Use(A);
app.Use(B);
app.Run(C);

Does A call B? Or does the runtime call A, then B? (Answer: A calls B. A holds a reference to B as next).

The Interview Questions They’ll Ask

Prepare to answer these:

  1. “Why does the order of middleware matter?”
  2. “What happens if you forget to call await next()?”
  3. “How do you write middleware that runs after the response is sent?” (Hint: You usually don’t, but Response.OnCompleted exists).

Hints in Layers

Hint 1: Definitions delegate Task RequestDelegate(HttpContext context);

Hint 2: The Builder IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);

Hint 3: Execution To run the pipeline, you need a “seed” delegate (usually a 404 handler) and then wrap it with all registered middleware.

Books That Will Help

Topic Book Chapter
Middleware “ASP.NET Core in Action” Ch. 3
Design Patterns “Head First Design Patterns” Decorator Pattern

Project 9: The Source Generator (Compile-Time Metaprogramming)

  • File: LEARN_DOTNET_CORE_DEEP_DIVE.md
  • Main Programming Language: C#
  • Alternative Programming Languages: -
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Compilation / Metaprogramming
  • Software or Tool: Microsoft.CodeAnalysis.CSharp (Roslyn)
  • Main Book: “Metaprogramming in .NET” by Kevin Hazzard

What you’ll build: A Source Generator that auto-generates a ToString() method for any class marked with [AutoString], and a high-performance “Enum-to-String” generator that uses switch cases instead of Reflection.

Why it teaches Compilation: You are effectively writing a plugin for the C# compiler. You will understand the difference between Syntax Trees (text) and Semantic Models (meaning). You will see how code generation can replace expensive Runtime Reflection (Project 5) with zero-cost static code.

Core challenges you’ll face:

  • The Compiler Pipeline: Debugging code that runs inside the IDE during compilation.
  • Syntax vs Semantics: Knowing that MyClass is a string (Syntax) vs knowing it resolves to System.String (Semantics).
  • Incremental Generation: Caching your generator so it doesn’t slow down the IDE on every keystroke.

Key Concepts:

  • Roslyn API: ISourceGenerator, GeneratorExecutionContext.
  • Abstract Syntax Trees (AST): Traversing code structure.
  • Partial Methods/Classes: How generated code merges with user code.

Difficulty: Advanced Time estimate: Weekend Prerequisites: Understanding of C# syntax structures.


Real World Outcome

You’ll delete thousands of lines of boilerplate code.

Example Output:

// User Code
[AutoString]
public partial class User {
    public string Name { get; set; }
    public int Age { get; set; }
}

// ... Compiler runs ...

// Generated Code (Invisible but usable)
public partial class User {
    public override string ToString() {
        return $"User {{ Name = {Name}, Age = {Age} }}";
    }
}

// Usage
Console.WriteLine(new User { Name = "Alice", Age = 30 });
// Output: User { Name = Alice, Age = 30 }

The Core Question You’re Answering

“How can I write code that writes code?”

Reflection is slow because it analyzes types at runtime. Source Generators analyze types at compile time and write the C# you would have written by hand.

Concepts You Must Understand First

Stop and research these before coding:

  1. Roslyn Syntax Visualizer
    • Install this Visual Studio extension. Look at the tree for class C { }.
    • Resource: “Roslyn SDK Overview” on MS Docs.
  2. Partial Classes
    • Why must the user class be partial for this to work?

Questions to Guide Your Design

Before implementing, think through these:

  1. Debugging: You can’t just F5 a generator. You need to launch a second VS instance or use Debugger.Launch().
  2. Diagnostics: How do you report an error if the user applies [AutoString] to a private class? (You emit a Diagnostic).

Thinking Exercise

The Switch Statement

Imagine an Enum Colors { Red, Green }. Write the C# code to convert it to string using a switch. Now, imagine writing a string builder that produces that code based on an IFieldSymbol list.

The Interview Questions They’ll Ask

Prepare to answer these:

  1. “Why are Source Generators preferred over Reflection for serialization?” (Performance + AOT compatibility).
  2. “What is the difference between an Analyzer and a Generator?”
  3. “Can a Source Generator modify existing code?” (No, only add to it).

Hints in Layers

Hint 1: The Setup You need a library project targeting .NET Standard 2.0 (standard for Roslyn) with EnforceExtendedAnalyzerRules set to true.

Hint 2: The Syntax Receiver Use ISyntaxContextReceiver to filter nodes. Don’t analyze every node; look for ClassDeclarationSyntax with at least one Attribute.

Hint 3: The Template Don’t get fancy with syntax factories initially. Just use StringBuilder and append the raw C# string. It’s uglier but easier to debug.

Books That Will Help

Topic Book Chapter
Roslyn “Roslyn Cookbook” Ch. 4-5
Metaprogramming “.NET Core in Action” Ch. 12

Project 10: The EventPipe Diagnostic Tool

  • File: LEARN_DOTNET_CORE_DEEP_DIVE.md
  • Main Programming Language: C#
  • Alternative Programming Languages: -
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 3: Advanced
  • Knowledge Area: CLR Diagnostics / Performance
  • Software or Tool: Microsoft.Diagnostics.NETCore.Client
  • Main Book: “Pro .NET Memory Management” (Tools section)

What you’ll build: A simplified version of dotnet-trace or dotnet-counters. Your tool will connect to a running .NET process (using its PID), enable CLR events (GC Start, JIT Start, Exception Thrown), and print them in real-time.

Why it teaches CLR Internals: The CLR constantly emits telemetry via “EventPipe.” Consuming this stream lets you see exactly when GCs happen, why they happen (Allocation vs Induced), and how long they take, without modifying the target app.

Core challenges you’ll face:

  • IPC (Inter-Process Communication): Connecting to the Diagnostic Port (Unix Domain Socket / Named Pipe) of another process.
  • Event Parsing: Decoding the binary payload of TraceEvent into meaningful fields (e.g., “Gen 2 GC caused by Low Memory”).
  • Providers & Keywords: Knowing which “Keywords” (bitmasks) to enable to get just the GC events and not the noisy Threading events.

Key Concepts:

  • EventPipe: The mechanism .NET uses to stream telemetry.
  • ETW / LTTng: The underlying OS tracing mechanisms EventPipe replaces/wraps.
  • Diagnostics Client Library: The API to control the runtime from outside.

Difficulty: Advanced Time estimate: 1-2 weeks Prerequisites: Project 7 (Processes).


Real World Outcome

You’ll diagnose apps without a debugger.

Example Output:

$ dotnet run -- trace --pid 1234
[Connected to Process 1234]
[10:00:01] JIT: Compiling Method 'Main' (IL: 54 bytes)
[10:00:05] GC: Start (Gen 0) - Reason: AllocSmall
[10:00:05] GC: End (Gen 0) - Paused: 2ms
[10:00:12] Exception: System.NullReferenceException thrown at Program.cs:42

The Core Question You’re Answering

“How does Application Insights or Datadog get data from my app?”

They don’t just guess. They attach to the runtime’s diagnostic pipe and ask for the data. You are building that agent.

Concepts You Must Understand First

Stop and research these before coding:

  1. Event Providers
    • What is the Microsoft-Windows-DotNETRuntime provider?
    • Resource: MS Docs “CLR ETW Providers”.
  2. Event Levels
    • Informational vs Verbose. Why does Verbose sometimes crash the app (Heisenbug)?

Questions to Guide Your Design

Before implementing, think through these:

  1. Discovery: How do you find which processes are .NET processes? (Hint: DiagnosticsClient.GetPublishedProcesses()).
  2. Serialization: The events come as raw bytes. You need TraceEvent library to parse them.

Thinking Exercise

The GC Trigger

If you see a GC Start event with Reason = Induced, what does that mean? (It means someone called GC.Collect(). This is usually a bug in production code. Your tool can detect this!)

The Interview Questions They’ll Ask

Prepare to answer these:

  1. “How is EventPipe different from ETW (Event Tracing for Windows)?”
  2. “What is the overhead of leaving Profiling enabled in production?”
  3. “Can you attach to a process that is running inside a Docker container?”

Hints in Layers

Hint 1: The Library NuGet package: Microsoft.Diagnostics.NETCore.Client is for controlling the session. Microsoft.Diagnostics.Tracing.TraceEvent is for parsing the data.

Hint 2: The Session You create a DiagnosticsClient, then client.StartEventPipeSession(providers). This returns a Stream.

Hint 3: The Parser Pass that Stream to EventPipeEventSource. Hook up source.Clr.All += ... handlers. Then call source.Process().

Books That Will Help

Topic Book Chapter
Diagnostics “Pro .NET Memory Management” Ch. 14 (Tools)
EventPipe MS Docs “EventPipe”

Project 11: The Vectorized Math Kernel (SIMD)

  • File: LEARN_DOTNET_CORE_DEEP_DIVE.md
  • Main Programming Language: C#
  • Alternative Programming Languages: C++ (AVX intrinsics)
  • Coolness Level: Level 5: Pure Magic
  • Business Potential: 2. The “Micro-SaaS” (High-perf libraries)
  • Difficulty: Level 4: Expert
  • Knowledge Area: CPU Architecture / Performance
  • Software or Tool: System.Numerics.Vectors, System.Runtime.Intrinsics
  • Main Book: “Pro .NET Memory Management” (Advanced chapters)

What you’ll build: A high-performance math library that performs operations on large arrays (Sum, Dot Product, Min/Max) using SIMD (Single Instruction, Multiple Data). You will write a standard loop version and a vectorized version, then benchmark them.

Why it teaches CPU Architecture: Standard code processes one number at a time. Modern CPUs can process 4, 8, or 16 numbers in a single clock cycle (SSE/AVX). .NET exposes this via Vector<T>. This project forces you to think about CPU registers, data alignment, and loop unrolling.

Core challenges you’ll face:

  • Hardware Intrinsics: Checking if the CPU supports AVX2 or SSE.
  • Block Processing: Handling the “tail” of an array that doesn’t fit into the vector size.
  • Benchmarking: Measuring nanosecond differences reliably (using BenchmarkDotNet).

Key Concepts:

  • SIMD: Single Instruction Multiple Data.
  • **Vector**: The hardware-agnostic wrapper.
  • Avx2 / Sse41: The hardware-specific classes.

Difficulty: Expert Time estimate: 1 week Prerequisites: Project 2 (Memory/Spans), basic Linear Algebra helps.


Real World Outcome

You’ll make code run 8x faster.

Example Output:

$ dotnet run -c Release
[Benchmark] Summing 10,000,000 integers

Method       | Mean      | Speedup
------------ | --------- | -------
StandardLoop | 12.5 ms   | 1.0x
Vectorized   | 1.6 ms    | 7.8x  <-- The power of AVX2

The Core Question You’re Answering

“Why is my CPU usage only 100% on one core, but efficiently used?”

Actually, even at 100%, you might be wasting cycles if you aren’t using the vector units. This project answers “How do I squeeze the silicon?”

Concepts You Must Understand First

Stop and research these before coding:

  1. Registers
    • What is a 256-bit YMM register? How many 32-bit ints fit inside it? (Hint: 8).
    • Resource: Intel Intrinsics Guide.
  2. Data Dependency
    • Why can’t you vectorize a Fibonacci sequence easily? (Each step depends on the last).

Questions to Guide Your Design

Before implementing, think through these:

  1. Vector Size: Vector<int>.Count depends on the hardware. It might be 4 (128-bit) or 8 (256-bit). Your code must adapt dynamically.
  2. The Tail: If you have 10 items and vector size is 4. You process 0-3, 4-7. What about 8-9? (You need a fallback scalar loop).

Thinking Exercise

Loop Unrolling

Manually unroll this loop 4 times:

for (int i = 0; i < len; i++) sum += arr[i];

Now imagine sum is a vector of 4 partial sums.

The Interview Questions They’ll Ask

Prepare to answer these:

  1. “What is the difference between Vector<T> and Vector128<T>?”
  2. “Why does data alignment matter for SIMD instructions?”
  3. “How does .NET JIT handle SIMD on a machine that doesn’t support it?” (Software fallback).

Hints in Layers

Hint 1: The API Start with System.Numerics.Vector<T>. It’s easier. Vector.Add(v1, v2).

Hint 2: The Cast Cast your Span<int> to Span<Vector<int>> using MemoryMarshal.Cast. This is the secret weapon. It instantly treats the array as chunks of vectors.

Hint 3: The Aggregate After the loop, you have a Vector<int> containing partial sums (e.g., [sum1, sum2, sum3, sum4]). You need to sum the elements of that vector to get the final result.

Books That Will Help

Topic Book Chapter
Performance “Writing High-Performance .NET Code” Ch. 4
SIMD MS Docs “Hardware Intrinsics”

Project 12: The Mini-CLR (Stack-Based VM)

  • File: LEARN_DOTNET_CORE_DEEP_DIVE.md
  • Main Programming Language: C#
  • Alternative Programming Languages: C++
  • Coolness Level: Level 5: Pure Magic
  • Business Potential: 5. The “Industry Disruptor” (Scripting Engines)
  • Difficulty: Level 5: Master
  • Knowledge Area: Compilers / Runtime
  • Software or Tool: None (Pure Logic)
  • Main Book: “Writing a Compiler in Go” (Concepts apply) or “Game Scripting Mastery”

What you’ll build: A tiny virtual machine that executes a custom bytecode. You will define an instruction set (PUSH, ADD, PRINT, JUMP), a stack, and an instruction pointer. You will write a “bytecode runner” that executes this “assembly” just like the real CLR executes IL.

Why it teaches Runtime: You are rebuilding the JIT/Interpreter part of the CLR (Project 1 showed you the IL, this project runs it). You will intimately understand the “Evaluation Stack,” stack frames, and why “Stack Overflow” happens.

Core challenges you’ll face:

  • The Execution Loop: while(true) { fetch; decode; execute; }.
  • The Evaluation Stack: Managing pushes/pops correctly without underflow.
  • Control Flow: Implementing JUMP instructions (modifying the Instruction Pointer) to create loops and if-statements.

Key Concepts:

  • Fetch-Decode-Execute Cycle: The heart of every CPU and VM.
  • Stack Machine vs Register Machine: Why .NET chose Stack (IL) over Register (Lua).
  • Opcodes: Defining your byte-to-action mapping.

Difficulty: Master Time estimate: 2 weeks Prerequisites: Project 1 (IL understanding).


Real World Outcome

You’ll run code you invented.

Example Output:

$ dotnet run -- vm program.bin
[VM] Loaded 15 instructions.
[VM] Executing...
  PUSH 10
  PUSH 20
  ADD
  PRINT
[Output]: 30
[VM] Halted. Stack depth: 0.

The Core Question You’re Answering

“How does a computer know that 0x02 means ‘Add’?”

It doesn’t. You tell it. You build the switch statement that gives meaning to numbers.

Concepts You Must Understand First

Stop and research these before coding:

  1. Stack Machine
    • To add 3 + 4: Push 3, Push 4, Add. (Add pops 2, pushes 7).
    • Resource: Wikipedia “Stack machine”.
  2. Instruction Pointer (IP)
    • What variable tracks “where we are”? What happens to it during a GOTO?

Questions to Guide Your Design

Before implementing, think through these:

  1. Instruction Format: Will you use fixed width (1 byte opcode, 4 byte operand)? Or variable width? (Fixed is easier).
  2. Memory: Do you need a Heap? Or just a Stack for now? (Start with just Stack).

Thinking Exercise

The Jump

Implement IF (TOP > 0) GOTO Label using stack ops.

  1. PUSH 0
  2. GT (Pops 2, pushes 1 if A > B)
  3. JMP_IF_TRUE target (Pops result, sets IP if true)

The Interview Questions They’ll Ask

Prepare to answer these:

  1. “Why is the CLR a stack machine?” (Compact code size).
  2. “What is a Stack Frame?” (Call context).
  3. “How would you implement a function call in your VM?” (Push return address, Jump).

Hints in Layers

Hint 1: The Stack Stack<int> is fine for prototype. int[] with a sp (stack pointer) index is faster and more realistic.

Hint 2: The Instructions Define an enum: OpCode { HALT=0, PUSH=1, ADD=2, ... }.

Hint 3: The Loop

int ip = 0;
while (ip < code.Length) {
    var op = (OpCode)code[ip];
    ip++;
    switch (op) { ... }
}

Books That Will Help

Topic Book Chapter
Interpreters “Crafting Interpreters” (Nystrom) Part 3 (Bytecode)
Virtual Machines “Virtual Machine Design and Implementation in C/C++” Ch. 1-3

Project Comparison Table

Project Difficulty Time Depth of Understanding Fun Factor
IL Inspector ⭐⭐ Weekend Deep (Runtime) ⭐⭐⭐
Memory Arena ⭐⭐⭐ 1 week Deep (Memory) ⭐⭐⭐⭐
Kestrel-Lite ⭐⭐⭐ 2 weeks Deep (Networking) ⭐⭐⭐⭐⭐
Async Scheduler ⭐⭐⭐⭐ 1-2 weeks Deep (Threading) ⭐⭐⭐
DI Container ⭐⭐⭐ 1 week Deep (Architecture) ⭐⭐⭐
Mini-ORM ⭐⭐⭐⭐⭐ 2-3 weeks Deep (Metaprogramming) ⭐⭐⭐⭐⭐
Process Manager ⭐⭐ Weekend Broad (OS) ⭐⭐⭐
Middleware Pipe ⭐⭐ Weekend Broad (Web) ⭐⭐
Source Generator ⭐⭐⭐ Weekend Deep (Compiler) ⭐⭐⭐⭐
EventPipe Tool ⭐⭐⭐ 1-2 weeks Deep (Diagnostics) ⭐⭐⭐
Vectorized Kernel ⭐⭐⭐⭐ 1 week Deep (CPU/SIMD) ⭐⭐⭐⭐⭐
Mini-CLR ⭐⭐⭐⭐⭐ 2 weeks Deep (Runtime Architecture) ⭐⭐⭐⭐⭐

Recommendation

Start with Project 1 (IL Inspector). It is low-investment but immediately changes how you view your code. It separates the “syntax” from the “machine.”

Then, move to Project 2 (Memory). Understanding the stack and heap is the single biggest differentiator between a Junior and Senior .NET engineer.

Finally, tackle Project 3 (Kestrel-Lite). This will give you the confidence that you understand the “Cloud” stack from the socket up.

For the truly ambitious, Project 12 (Mini-CLR) is the ultimate test. If you can build a VM, you can learn anything.


Final Overall Project: The Distributed Plugin Runner

What you’ll build: A distributed task execution system.

  1. The Host: A generic console app that listens on a port (Project 3).
  2. The Plugins: Users write DLLs containing tasks. The Host loads them using AssemblyLoadContext (Advanced Project 1 concept).
  3. The Memory: Tasks are allocated in a custom MemoryContext to track usage (Project 2).
  4. The Wiring: Dependencies are injected via your custom DI container (Project 5).
  5. The Protocol: Nodes talk to each other to distribute work (Project 3).
  6. The Monitoring: A sidecar process (Project 10) watches the health of the runner.
  7. The Speed: Core math tasks use SIMD (Project 11).

This combines Reflection, Networking, Memory Management, Dependency Injection, Async, Diagnostics, and SIMD into one cohesive system. It is effectively a mini-Kubernetes pod written in pure C#.


Summary

This learning path covers .NET (Core) through 12 hands-on projects. Here’s the complete list:

# Project Name Main Language Difficulty Time Estimate
1 The IL Inspector C# Intermediate Weekend
2 Memory Inspector & Allocator C# Advanced 1 week
3 Kestrel-Lite (Socket Server) C# Advanced 2 weeks
4 Async Task Scheduler C# Expert 1-2 weeks
5 DI Container C# Advanced 1 week
6 Mini-ORM (Expression Trees) C# Master 2-3 weeks
7 Cross-Platform Process Manager C# Intermediate Weekend
8 Middleware Pipeline C# Intermediate Weekend
9 Source Generator C# Advanced Weekend
10 EventPipe Diagnostic Tool C# Advanced 1-2 weeks
11 Vectorized Math Kernel C# Expert 1 week
12 Mini-CLR (Stack VM) C# Master 2 weeks

For beginners: Start with Project 7 and Project 8 to get wins with the framework. For intermediate: Jump to Project 1 and Project 2 to understand the “under the hood” mechanics. For advanced: Focus on Project 4 and Project 6 to master the hardest parts of the ecosystem (Async and Expression Trees). For masters: Project 11 and Project 12 will test your knowledge of hardware and runtime theory.

Expected Outcomes

After completing these projects, you will:

  • Read IL and understand compiler optimizations.
  • Visualize memory layout and manage GC pressure.
  • Write non-blocking network code without relying on framework magic.
  • Understand the “magic” behind await, [Inject], LINQ, and Source Generators.
  • Be able to debug complex production issues related to threading, memory, and JIT.
  • Write high-performance SIMD code that fully utilizes modern CPUs.

You’ll have built 12 working projects that demonstrate deep understanding of .NET from first principles.