--- LOGGING START ---
--- ERROR HANDLER START ---
--- VALIDATOR START ---
--- GREETER START ---
Hello Kristian!
ERROR: Oops! Something went wrong...
--- ERROR HANDLER END ---
--- LOGGING END ---
-
-
Save hoangitk/9d2b64ae32674f24ccf6fd77043ef362 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Linq; | |
using Microsoft.Extensions.DependencyInjection; | |
using Microsoft.Extensions.DependencyInjection.Extensions; | |
public class Program | |
{ | |
public static void Main(string[] args) | |
{ | |
var services = new ServiceCollection(); | |
services.AddSingleton<INameValidator, NameValidator>(); | |
// Imagine this was added by MVC | |
services.AddSingleton<IGreeter, Greeter>(); | |
// Either | |
// services.Decorate<IGreeter>((provider, inner) => new ValidatingGreeter(inner, provider.GetRequiredService<INameValidator>())); | |
// services.Decorate<IGreeter>((_, inner) => new ErrorHandlingGreeter(inner)); | |
// services.Decorate<IGreeter>((_, inner) => new LoggingGreeter(inner)); | |
// Or | |
services.Decorate<IGreeter>((provider, inner) => | |
new LoggingGreeter( | |
new ErrorHandlingGreeter( | |
new ValidatingGreeter(inner, | |
provider.GetRequiredService<INameValidator>())))); | |
services.BuildServiceProvider() | |
.GetRequiredService<IGreeter>() | |
.Greet("Kristian"); | |
} | |
} | |
public static class ServiceCollectionExtensions | |
{ | |
public static IServiceCollection Decorate<TService>(this IServiceCollection services, Func<IServiceProvider, TService, TService> decorator) | |
where TService : class | |
{ | |
return services.Replace(services | |
.Single(descriptor => descriptor.ServiceType == typeof(TService)) | |
.Decorate(decorator)); | |
} | |
private static ServiceDescriptor Decorate<TService>(this ServiceDescriptor descriptor, Func<IServiceProvider, TService, TService> decorator) | |
{ | |
return ServiceDescriptor.Describe(descriptor.ServiceType, | |
provider => decorator(provider, (TService) descriptor.GetInstance(provider)), | |
descriptor.Lifetime); | |
} | |
private static object GetInstance(this ServiceDescriptor descriptor, IServiceProvider provider) | |
{ | |
return descriptor.ImplementationInstance | |
?? (descriptor.ImplementationType != null | |
? provider.GetServiceOrCreateInstance(descriptor.ImplementationType) | |
: descriptor.ImplementationFactory(provider)); | |
} | |
private static object GetServiceOrCreateInstance(this IServiceProvider provider, Type type) | |
{ | |
return ActivatorUtilities.GetServiceOrCreateInstance(provider, type); | |
} | |
} | |
public interface IGreeter | |
{ | |
void Greet(string name); | |
} | |
public class Greeter : IGreeter | |
{ | |
public void Greet(string name) | |
{ | |
Console.WriteLine("--- GREETER START ---"); | |
Console.WriteLine($"Hello {name}!"); | |
throw new Exception("Oops! Something went wrong..."); | |
Console.WriteLine("--- GREETER END ---"); | |
} | |
} | |
public class LoggingGreeter : IGreeter | |
{ | |
private readonly IGreeter _inner; | |
public LoggingGreeter(IGreeter inner) | |
{ | |
_inner = inner; | |
} | |
public void Greet(string name) | |
{ | |
Console.WriteLine("--- LOGGING START ---"); | |
_inner.Greet(name); | |
Console.WriteLine("--- LOGGING END ---"); | |
} | |
} | |
public interface INameValidator | |
{ | |
bool IsValid(string name); | |
} | |
public class NameValidator : INameValidator | |
{ | |
public bool IsValid(string name) | |
{ | |
return name.StartsWith("K"); | |
} | |
} | |
public class ValidatingGreeter : IGreeter | |
{ | |
private readonly IGreeter _inner; | |
private readonly INameValidator _validator; | |
public ValidatingGreeter(IGreeter inner, INameValidator validator) | |
{ | |
_inner = inner; | |
_validator = validator; | |
} | |
public void Greet(string name) | |
{ | |
Console.WriteLine("--- VALIDATOR START ---"); | |
if (!_validator.IsValid(name)) | |
{ | |
throw new InvalidOperationException("Invalid name."); | |
} | |
_inner.Greet(name); | |
Console.WriteLine("--- VALIDATOR END ---"); | |
} | |
} | |
public class ErrorHandlingGreeter : IGreeter | |
{ | |
private readonly IGreeter _inner; | |
public ErrorHandlingGreeter(IGreeter inner) | |
{ | |
_inner = inner; | |
} | |
public void Greet(string name) | |
{ | |
Console.WriteLine("--- ERROR HANDLER START ---"); | |
try | |
{ | |
_inner.Greet(name); | |
} | |
catch (Exception e) | |
{ | |
Console.WriteLine($"ERROR: {e.Message}"); | |
} | |
Console.WriteLine("--- ERROR HANDLER END ---"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment