Master enterprise patterns: dependency injection, HTTP client usage, and expression trees for dynamic code.
Build scalable, testable applications with modern .NET patterns.
public interface ILogger { void Log(string message); }
public interface IDataService { string GetData(); }
public class ConsoleLogger : ILogger
{
public void Log(string message) => Console.WriteLine($"[LOG] {message}");
}
public class DataService : IDataService
{
private readonly ILogger _logger;
public DataService(ILogger logger) { _logger = logger; }
public string GetData() { _logger.Log("Fetching data"); return "Hello from DataService"; }
}
2. Register services with ServiceCollection:
var services = new ServiceCollection();
services.AddSingleton<ILogger, ConsoleLogger>();
services.AddTransient<IDataService, DataService>();
3. Build ServiceProvider and resolve:
var provider = services.BuildServiceProvider();
var dataService = provider.GetRequiredService<IDataService>();
4. Understand lifetimes: Singleton, Scoped, Transient.Microsoft.Extensions.DependencyInjection NuGet[LOG] Fetching data
Result: Hello from DataService
Same singleton? True
Same transient? False
public interface ILogger { void Log(string msg); }services.AddSingleton<ILogger, ConsoleLogger>();var provider = services.BuildServiceProvider();provider.GetRequiredService<IDataService>();Review feedback below
HttpClient to make GET and POST requests, handle responses, and deserialize JSON.using var client = new HttpClient();
client.BaseAddress = new Uri("https://api.example.com/");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
2. Make GET request:
var response = await client.GetAsync("users/1");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
var user = JsonSerializer.Deserialize<User>(json);
3. Make POST request with JSON body:
var newUser = new User { Name = "Alice" };
var content = new StringContent(JsonSerializer.Serialize(newUser), Encoding.UTF8, "application/json");
var postResponse = await client.PostAsync("users", content);
4. Handle errors: Check status codes, use try/catch.IHttpClientFactory in real apps (avoids socket exhaustion)response.EnsureSuccessStatusCode() to throw on errorsReadFromJsonAsync<T>() simplifies deserializationGET /users/1 - Status: 200 OK
User: { Id: 1, Name: "Alice" }
POST /users - Status: 201 Created
Created user ID: 2
using var client = new HttpClient();await client.GetAsync("endpoint")await client.PostAsync("endpoint", content)new StringContent(json, Encoding.UTF8, "application/json")Review feedback below
Expression<Func<int, int, int>> addExpr = (a, b) => a + b;
var compiled = addExpr.Compile();
int result = compiled(3, 5); // 8
2. Build expression tree manually:
var paramX = Expression.Parameter(typeof(int), "x");
var paramY = Expression.Parameter(typeof(int), "y");
var body = Expression.Add(paramX, paramY);
var lambda = Expression.Lambda<Func<int, int, int>>(body, paramX, paramY);
var func = lambda.Compile();
3. Inspect expression tree: Walk the tree structure.// Build: x => x.PropertyName
var param = Expression.Parameter(typeof(T), "x");
var property = Expression.Property(param, propertyName);
var lambda = Expression.Lambda(property, param);Expression.Lambda wraps body into callable delegateLambda from code: 3 + 5 = 8
Manual expression: 10 * 4 = 40
Expression type: Lambda
Body type: Add
Dynamic getter: Name = Alice
Expression<Func<int,int>> e = x => x * 2;var func = expression.Compile();Expression.Parameter, Expression.AddExpression.Lambda<Func<...>>(body, params)Review feedback below