Skip to content

Instantly share code, notes, and snippets.

@En3Tho
Last active July 21, 2022 06:28
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save En3Tho/628429c6b21c901673183d80fa659d85 to your computer and use it in GitHub Desktop.
Save En3Tho/628429c6b21c901673183d80fa659d85 to your computer and use it in GitHub Desktop.
using System;
using System.Linq;
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
namespace AutoInject
{
public enum InjectType
{
Singleton,
Scoped,
Transient
}
[AttributeUsage(AttributeTargets.Class)]
public class InjectableAttribute : Attribute
{
public InjectType InjectType { get; }
public Type? ServiceType { get; }
public InjectableAttribute(InjectType injectType, Type? underlyingType) => (InjectType, ServiceType) = (injectType, underlyingType); // implement enum and underlying type checks
public InjectableAttribute(InjectType injectType) : this(injectType, null) { }
}
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddInjectables(this IServiceCollection serviceCollection)
{
var types =
Assembly
.GetExecutingAssembly()
.GetTypes()
.Where(x => x.GetCustomAttribute(typeof(InjectableAttribute)) != null)
.Select(x => (x, (InjectableAttribute)x.GetCustomAttribute(typeof(InjectableAttribute))!));
foreach (var (implementationType, attribute) in types)
{
switch (attribute.InjectType)
{
case InjectType.Singleton:
if (attribute.ServiceType is not null)
serviceCollection.AddSingleton(attribute.ServiceType, implementationType);
else
serviceCollection.AddSingleton(implementationType);
break;
case InjectType.Scoped:
if (attribute.ServiceType is not null)
serviceCollection.AddScoped(attribute.ServiceType, implementationType);
else
serviceCollection.AddScoped(implementationType);
break;
case InjectType.Transient:
if (attribute.ServiceType is not null)
serviceCollection.AddTransient(attribute.ServiceType, implementationType);
else
serviceCollection.AddTransient(implementationType);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
return serviceCollection;
}
}
}
namespace AutoInject
{
[Injectable(InjectType.Singleton, typeof(IValueService))]
public class ValueService : IValueService
{
public int Value => 1;
}
public interface IValueService
{
int Value { get; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment