Skip to content

Instantly share code, notes, and snippets.

@waynebrantley
Last active September 9, 2023 20:35
Show Gist options
  • Save waynebrantley/b4a9c3e6161c4edbc47bece6f492123a to your computer and use it in GitHub Desktop.
Save waynebrantley/b4a9c3e6161c4edbc47bece6f492123a to your computer and use it in GitHub Desktop.
Scrutor functazure function
public static bool TryDecorate(this IServiceCollection services, DecorationStrategy strategy, bool useFactory)
{
if (!useFactory)
return services.TryDecorate(strategy);
var decorated = false;
for (var i = services.Count - 1; i >= 0; i--)
{
var serviceDescriptor = services[i];
if (serviceDescriptor.ServiceType is DecoratedType)
{
continue; // Service has already been decorated.
}
if (!strategy.CanDecorate(serviceDescriptor.ServiceType))
{
continue; // Unable to decorate using the specified strategy.
}
var decoratedType = new DecoratedType(serviceDescriptor.ServiceType);
// Insert decorated
services.Add(serviceDescriptor.WithDecoratedTypeNext(decoratedType));
// Replace decorator
services[i] = serviceDescriptor.WithImplementationFactory(strategy.CreateDecorator(decoratedType));
decorated = true;
}
return decorated;
}
public static ServiceDescriptor WithImplementationFactory(this ServiceDescriptor descriptor, Func<IServiceProvider, object> implementationFactory) =>
new(descriptor.ServiceType, implementationFactory, descriptor.Lifetime);
public static ServiceDescriptor WithDecoratedTypeNext(this ServiceDescriptor descriptor, DecoratedType serviceType) => descriptor switch
{
{ ImplementationType: not null } => new ServiceDescriptor(serviceType, descriptor.ImplementationType.ToFactory2(), descriptor.Lifetime),
{ ImplementationFactory: not null } => new ServiceDescriptor(serviceType, descriptor.ImplementationFactory, descriptor.Lifetime),
{ ImplementationInstance: not null } => new ServiceDescriptor(serviceType, descriptor.ImplementationInstance),
_ => throw new ArgumentException($"No implementation factory or instance or type found for {descriptor.ServiceType}.", nameof(descriptor))
};
private static Func<IServiceProvider, object> ToFactory2(this Type serviceType)
{
return new Cache(serviceType).Create;
}
public class Cache
{
private readonly Func<ObjectFactory> _createActivator;
private ObjectFactory? _activator;
private bool _initialized;
private object? _lock;
public Cache(Type type)
{
_createActivator = () => ActivatorUtilities.CreateFactory(type, Array.Empty<Type>());
}
public ObjectFactory Activator => LazyInitializer.EnsureInitialized(
ref _activator,
ref _initialized,
ref _lock!,
_createActivator)!;
public object Create(IServiceProvider services) => Activator(services, Array.Empty<object>());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment