自动注入实现
实现方法
- 通过继承xx接口实现单例(singleton),作用域(scoped),瞬时(transient)三种方式注入
- 实现ConfigService方法进行自定义注入
- 通过反射加载程序集获取继承接口的类
1. 定义被继承的接口
public interface IServiceRegistrar
{
/// <summary>
/// 配置注册
/// </summary>
/// <param name="service">服务</param>
void ConfigService(IServiceCollection service);
}
/// <summary>
/// Scoped方式注入
/// </summary>
public interface IScoped
{
}
/// <summary>
/// Singleton方式注入
/// </summary>
public interface ISingleton
{
}
/// <summary>
/// Transient方式注入
/// </summary>
public interface ITransient
{
}
- 定义扩展方法进行自动注册,其中
RuntimeUtils.GetAllAssemblies()
是自己写的获取所有程序集的方法,排除了nuget和microsoft程序集和system程序集,核心注册方法
/// <summary>
/// 注册系统服务,使用继承注册器<see cref="IServiceRegistrar" />或<see cref="IScoped" />或<see cref="ITransient" />或
/// <see cref="ISingleton" />
/// </summary>
/// <param name="service"></param>
public static void AddHServices(this IServiceCollection service)
{
var aseArray = RuntimeUtils.GetAllAssemblies();
var t1 = typeof(IServiceRegistrar);
var t2 = typeof(IScoped);
var t3 = typeof(ITransient);
var t4 = typeof(ISingleton);
var typeList = new List<Type>
{
t1, t2, t3, t4
};
foreach (var ase in aseArray)
{
var list = (from type in ase.GetTypes()
where typeList.Any(t => t.IsAssignableFrom(type)) && !type.IsAbstract && type.IsClass
select type).ToList();
list.ForEach(x =>
{
if (x.IsInterface) return;
if (x.IsAssignableTo(t1))
{
var obj = Activator.CreateInstance(x);
x.GetMethod("ConfigService")!.Invoke(obj, new object?[] { service });
}
else
{
var implTypes = x.GetInterfaces().Where(x1 => !typeList.Contains(x1));
foreach (var implType in implTypes)
{
if (x.IsAssignableTo(t2))
service.AddScoped(implType, x);
if (x.IsAssignableTo(t3))
service.AddTransient(implType, x);
if (x.IsAssignableTo(t4))
service.AddSingleton(implType, x);
}
}
});
}
}
- 在program.cs添加
builder.Services.AddHServices();
4. RuntimeUtils代码,需要引入nugetMicrosoft.Extensions.DependencyModel
public static class RuntimeUtils
{
/// <summary>
/// 获取项目程序集,排除所有的系统程序集(Microsoft.***、System.***等)、Nuget下载包
/// </summary>
/// <returns></returns>
public static IList<Assembly> GetAllAssemblies()
{
var list = new List<Assembly>();
var dependencyContext = DependencyContext.Default;
if (dependencyContext == null) return list;
var libs = dependencyContext.CompileLibraries.Where(lib =>
!lib.Serviceable && lib.Type != "package"); //排除所有的系统程序集、Nuget下载包
foreach (var lib in libs)
try
{
var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));
list.Add(assembly);
}
catch (Exception)
{
// ignored
}
return list;
}
public static Assembly GetAssembly(string assemblyName)
{
return GetAllAssemblies().FirstOrDefault(assembly => assembly.FullName.Contains(assemblyName));
}
public static IList<Type> GetAllTypes()
{
var list = new List<Type>();
foreach (var assembly in GetAllAssemblies())
{
var typeInfos = assembly.DefinedTypes;
foreach (var typeInfo in typeInfos) list.Add(typeInfo.AsType());
}
return list;
}
public static IList<Type> GetTypesByAssembly(string assemblyName)
{
var list = new List<Type>();
var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyName));
var typeInfos = assembly.DefinedTypes;
foreach (var typeInfo in typeInfos) list.Add(typeInfo.AsType());
return list;
}
public static Type GetImplementType(string typeName, Type baseInterfaceType)
{
return GetAllTypes().FirstOrDefault(t =>
{
if (t.Name == typeName &&
t.GetTypeInfo().GetInterfaces().Any(b => b.Name == baseInterfaceType.Name))
{
var typeInfo = t.GetTypeInfo();
return typeInfo.IsClass && !typeInfo.IsAbstract && !typeInfo.IsGenericType;
}
return false;
});
}
}