Introduction
.NET Core has become the backbone of modern enterprise applications due to its modular architecture, cross-platform support, and high performance.
To build scalable and reliable systems, developers must understand key advanced concepts:
Let's explore each with real-world insights and code examples.
1. Dependency Injection (DI) in .NET Core
What is DI?
Dependency Injection (DI) is a design pattern that helps create loosely-coupled, maintainable applications by providing dependencies instead of manually creating them.
.NET Core has DI built in, unlike older .NET Framework versions, where third-party tools (Autofac, Unity, Ninject) were required.
Types of DI Lifetimes
| Lifetime | Purpose | Example |
|---|
| Singleton | One instance throughout app life | Config services, cache |
| Scoped | One instance per request | DB context |
| Transient | New instance every call | Lightweight services |
Real-Time Example: Registering Services
Service Interface
public interface IMessageService
{
string SendMessage();
}
Service Implementation
public class EmailService : IMessageService
{
public string SendMessage() => "Email Sent Successfully!";
}
Registering in the Program.cs
builder.Services.AddScoped<IMessageService, EmailService>();
Injecting in Controller
public class NotificationController : ControllerBase
{
private readonly IMessageService _messageService;
public NotificationController(IMessageService messageService)
{
_messageService = messageService;
}
[HttpGet("send-mail")]
public string SendMail() => _messageService.SendMessage();
}
DI Best Practices
Avoid the service locator pattern
Do not inject many services into the constructor (use the Facade pattern)
Use the IOptions pattern for configuration
Manage lifetimes correctly — Singleton service must not depend on Scoped services
2. Middleware in ASP.NET Core
What is Middleware?
Middleware is a software component added to the HTTP request pipeline to handle:
Authentication
Logs
Exception handling
CORS
Response compression
Custom Middleware Example
public class RequestLoggingMiddleware
{
private readonly RequestDelegate _next;
public RequestLoggingMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
Console.WriteLine($"Request: {context.Request.Path}");
await _next(context);
Console.WriteLine($"Response: {context.Response.StatusCode}");
}
}
Register the Middleware
app.UseMiddleware<RequestLoggingMiddleware>();
Middleware Order Matters
app.UseExceptionHandler();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints();
Changing order may break security or routing.
3. Memory Leaks in .NET Core
What Causes Memory Leaks?
Even though .NET has a Garbage Collector, memory leaks still happen due to:
| Reason | Example |
|---|
| Unreleased unmanaged resources | File handles, database connections |
| Improper event subscriptions | Event handlers not removed |
| Singleton misuse | Holding heavy objects |
| Static references | Cached objects not cleared |
Memory Leak Example
public class MyService
{
private static List<byte[]> _buffer = new();
public void FillMemory()
{
_buffer.Add(new byte[1024 * 1024]); // 1MB
}
}
Running repeatedly = OutOfMemory
Fix
Use DI lifetimes correctly
Dispose resources with using
Remove event handlers
Monitor memory usage with tools:
Example cleanup
public class FileService : IDisposable
{
private FileStream _stream;
public FileService()
{
_stream = File.OpenRead("data.txt");
}
public void Dispose()
{
_stream?.Dispose();
}
}
Conclusion
Advanced .NET Core architecture requires developers to understand:
Proper DI usage for loose coupling
Efficient middleware pipeline
Memory management best practices
Mastering these ensures your application stays:
1. Highly scalable
2. Easy to maintain
3.High-performance
Interview Quick-Fire Questions
| Question | Key Concept |
|---|
| What is DI? | Loose coupling, easier testing |
| Difference between AddScoped vs AddSingleton | Object lifetime |
| What is middleware? | Request pipeline handlers |
| How to detect memory leaks? | Profilers, GC logs |
| Why avoid async void? | Can't track errors or memory leaks |