通常情况下我们都是在program.cs文件中依次注入我们需要的服务:
builder.Services.AddTransient(IUserService,UserService);
但是,如果我们的项目变得庞大后,功能越来越多,就会有许多的服务需要我们去注入,这样会使得产生许多不必要的操作,因此我们可以使用Autofac来自动注入我们的服务。基本步骤如下:
- 首先我们创建一个空的BaseService类
public class BaseService { }
- 我们通过反射获取所有继承了这个类的子类并自动注入
/// <summary> /// 获取所有继承BaseRepository的实现类并注册到DI容器中 /// </summary> public static void AddClubService(this WebApplicationBuilder builder) { //获取所有程序集(包括未使用的) var assemblies = AppDomain.CurrentDomain.GetReferanceAssemblies(); foreach (var assembly in assemblies) { if (typeof(BaseService).Assembly.Equals(assembly)) { List<Type> types = assembly.GetTypes().Where(t => t.BaseType == typeof(BaseService)).ToList(); types.ForEach(impl => { // 获取类实现的接口 Type[] interfaces = impl.GetInterfaces(); interfaces.ToList().ForEach(i => { builder.Services.AddTransient(i, impl); }); }); } } }
这里我使用的是自定义的GetReferanceAssemblies()方法,而不是GetAssemblies(),是因为GetAssemblies只会获取已经使用过的程序集。GetReferanceAssemblies()方法内容如下:
/// <summary> /// Assembly注入扩展,用于获取所有程序集,包括未使用过的 /// </summary> public static class AssemblyExtension { public static List<Assembly> GetReferanceAssemblies(this AppDomain domain) { var list = new List<Assembly>(); // 加载当前AppDomain中加载的所有程序集 domain.GetAssemblies().ToList().ForEach(i => { GetReferanceAssemblies(i, list); }); return list; } /// <summary> /// 递归获取程序集的引用程序集 /// </summary> /// <param name="assembly"></param> /// <param name="list"></param> static void GetReferanceAssemblies(Assembly assembly, List<Assembly> list) { // 获取指定程序集引用的所有程序集 assembly.GetReferencedAssemblies().ToList().ForEach(i => { // 加载引用的程序集 var ass = Assembly.Load(i); if (!list.Contains(ass)) { list.Add(ass); // 处理新增的程序集的引用程序集 GetReferanceAssemblies(ass, list); } }); } }
- 此时我们在Program.cs中将此服务注入
builder.AddClubService();
这样我们就实现了利用反射实现服务的自动注入