给微软的依赖注入框架写一些扩展方法
給微軟的依賴注入框架寫一些擴展方法
Intro
現在在項目里大多都是直接使用微軟的依賴注入框架,而微軟的注入方式比較簡單,不如 AutoFac 使用起來靈活,于是想給微軟的依賴注入增加一些擴展,使得可以像AutoFac 一樣比較靈活的注冊服務
Extensions
RegisterTypeAsImplementedInterface
將類型注冊為其實現的接口,比如 pubicclassUserService:IUserService,IUserRepository{},
注冊 UserService 為 IUserService 和 IUserRepository
等效于:
services.AddSingleton<IUserService, UserService>(); services.AddSingleton<IUserRepository, UserService>();實現代碼:
/// <summary> /// RegisterTypeAsImplementedInterfaces /// </summary> /// <param name="services">services</param> /// <param name="type">type</param> /// <param name="serviceLifetime">service lifetime</param> /// <returns>services</returns> public static IServiceCollection RegisterTypeAsImplementedInterfaces(this IServiceCollection services, Type type, ServiceLifetime serviceLifetime = ServiceLifetime.Singleton) {if (type != null){foreach (var interfaceType in type.GetImplementedInterfaces()){services.Add(new ServiceDescriptor(interfaceType, type, serviceLifetime));}}return services; }RegisterAssemblyTypesAsImplementedInterface
在上面的基礎上,加載指定程序集中的類型(不指定程序集則使用當前應用程序域中所有程序集),可以通過 typesFilter 來過濾要注冊的類型
使用示例:
services.RegisterAssemblyTypesAsImplementedInterface(t => !t.IsAbstract && t.IsClass && t.IsAssignableTo<IEventHandler>(), typeof(NoticeViewEventHandler).Assembly);實現源碼:
/// <summary> /// RegisterTypeAsImplementedInterfaces /// </summary> /// <param name="services">services</param> /// <param name="assemblies">assemblies</param> /// <returns>services</returns> public static IServiceCollection RegisterAssemblyTypesAsImplementedInterfaces(this IServiceCollection services,params Assembly[] assemblies)=> RegisterAssemblyTypesAsImplementedInterfaces(services, typesFilter: null, ServiceLifetime.Singleton, assemblies); /// <summary> /// RegisterTypeAsImplementedInterfaces /// </summary> /// <param name="services">services</param> /// <param name="serviceLifetime">service lifetime</param> /// <param name="assemblies">assemblies</param> /// <returns>services</returns> public static IServiceCollection RegisterAssemblyTypesAsImplementedInterfaces(this IServiceCollection services,ServiceLifetime serviceLifetime, params Assembly[] assemblies)=> RegisterAssemblyTypesAsImplementedInterfaces(services, typesFilter: null, serviceLifetime, assemblies); /// <summary> /// RegisterTypeAsImplementedInterfaces, singleton by default /// </summary> /// <param name="services">services</param> /// <param name="typesFilter">filter types to register</param> /// <param name="assemblies">assemblies</param> /// <returns>services</returns> public static IServiceCollection RegisterAssemblyTypesAsImplementedInterfaces(this IServiceCollection services, Func<Type, bool> typesFilter, params Assembly[] assemblies)=> RegisterAssemblyTypesAsImplementedInterfaces(services, typesFilter: typesFilter, ServiceLifetime.Singleton, assemblies); /// <summary> /// RegisterTypeAsImplementedInterfaces /// </summary> /// <param name="services">services</param> /// <param name="typesFilter">filter types to register</param> /// <param name="serviceLifetime">service lifetime</param> /// <param name="assemblies">assemblies</param> /// <returns>services</returns> public static IServiceCollection RegisterAssemblyTypesAsImplementedInterfaces(this IServiceCollection services, Func<Type, bool> typesFilter, ServiceLifetime serviceLifetime, params Assembly[] assemblies) {if (assemblies == null || assemblies.Length == 0){assemblies = ReflectHelper.GetAssemblies();}var types = assemblies.Select(assembly => assembly.GetExportedTypes()).SelectMany(t => t);if (typesFilter != null){types = types.Where(typesFilter);}foreach (var type in types){foreach (var implementedInterface in type.GetImplementedInterfaces()){services.Add(new ServiceDescriptor(implementedInterface, type, serviceLifetime));}}return services; }RegisterAssemblyTypes
注冊類型,這相當于 AutoFac 中 RegisterAssemblyTypes().AsSelf()
services.RegisterAssemblyTypes(t => !t.IsAbstract && t.IsClass && t.IsAssignableTo<IEventHandler>(), typeof(NoticeViewEventHandler).Assembly);實現源碼:
/// <summary> /// RegisterAssemblyTypes /// </summary> /// <param name="services">services</param> /// <param name="assemblies">assemblies</param> /// <returns>services</returns> public static IServiceCollection RegisterAssemblyTypes(this IServiceCollection services, params Assembly[] assemblies)=> RegisterAssemblyTypes(services, null, ServiceLifetime.Singleton, assemblies); /// <summary> /// RegisterAssemblyTypes /// </summary> /// <param name="services">services</param> /// <param name="serviceLifetime">service lifetime</param> /// <param name="assemblies">assemblies</param> /// <returns>services</returns> public static IServiceCollection RegisterAssemblyTypes(this IServiceCollection services,ServiceLifetime serviceLifetime, params Assembly[] assemblies)=> RegisterAssemblyTypes(services, null, serviceLifetime, assemblies); /// <summary> /// RegisterAssemblyTypes /// </summary> /// <param name="services">services</param> /// <param name="typesFilter">filter types to register</param> /// <param name="assemblies">assemblies</param> /// <returns>services</returns> public static IServiceCollection RegisterAssemblyTypes(this IServiceCollection services,Func<Type, bool> typesFilter, params Assembly[] assemblies)=> RegisterAssemblyTypes(services, typesFilter, ServiceLifetime.Singleton, assemblies); /// <summary> /// RegisterAssemblyTypes /// </summary> /// <param name="services">services</param> /// <param name="typesFilter">filter types to register</param> /// <param name="serviceLifetime">service lifetime</param> /// <param name="assemblies">assemblies</param> /// <returns>services</returns> public static IServiceCollection RegisterAssemblyTypes(this IServiceCollection services, Func<Type, bool> typesFilter, ServiceLifetime serviceLifetime, params Assembly[] assemblies) {if (assemblies == null || assemblies.Length == 0){assemblies = ReflectHelper.GetAssemblies();}var types = assemblies.Select(assembly => assembly.GetExportedTypes()).SelectMany(t => t);if (typesFilter != null){types = types.Where(typesFilter);}foreach (var type in types){services.Add(new ServiceDescriptor(type, type, serviceLifetime));}return services; }ServiceModule
在 AutoFac 中有一個 Module 的概念可以讓我們更方便的注冊,一般可以在一個 Module 里注冊需要服務注冊的服務,這樣注冊的好處在于容易做插件化,新的插件需要注冊什么樣的服務,外界并不知道,如果用 Module 的注冊方式,我只需要調用插件中的 Module 就可以注冊所需要的服務了
IServiceModule
類似于 AutoFac 中的 Module,我們也可以定義一個 IServiceModule,定義一個 ConfigueServices(IServiceCollectionservices) 的方法用來注冊服務
public interface IServiceModule {void ConfigureServices(IServiceCollection services); }ServiceModule Demo
public class BusinessServiceModule : IServiceModule {public void ConfigureServices(IServiceCollection services){services.AddEFRepository();services.AddBLL();services.TryAddScoped<ReservationHelper>();services.TryAddSingleton<CaptchaVerifyHelper>();services.TryAddSingleton<OperLogHelper>();} }RegisterAssemblyModules
上面我們定義了一個 Module,下面來定義一個擴展方法來注冊 module 中的服務信息
使用示例:
// load service modules services.RegisterAssemblyModules(pluginAssemblies);實現源碼:
/// <summary> /// RegisterAssemblyModules /// </summary> /// <param name="services">services</param> /// <param name="assemblies">assemblies</param> /// <returns>services</returns> public static IServiceCollection RegisterAssemblyModules([NotNull] this IServiceCollection services, params Assembly[] assemblies) {if (assemblies == null || assemblies.Length == 0){assemblies = ReflectHelper.GetAssemblies();}foreach (var type in assemblies.SelectMany(ass => ass.GetTypes()).Where(t => t.IsClass && !t.IsAbstract && typeof(IServiceModule).IsAssignableFrom(t))){try{if (Activator.CreateInstance(type) is IServiceModule module){module.ConfigureServices(services);}}catch (Exception e){Console.WriteLine(e);}}return services; }Reference
https://github.com/WeihanLi/WeihanLi.Common/blob/58cec5fe93baa3ad73df6e339e2fcb609a7b4b79/src/WeihanLi.Common/Extensions/ServiceCollectionExtension.cs
https://github.com/WeihanLi/ActivityReservation/blob/dev/ActivityReservation/Startup.cs
https://github.com/WeihanLi/ActivityReservation/blob/dev/ActivityReservation.Helper/Services/BusinessServiceModule.cs
https://github.com/WeihanLi/DbTool/blob/wpf-dev/DbTool/App.xaml.cs
https://autofac.readthedocs.io/en/latest/configuration/modules.html
總結
以上是生活随笔為你收集整理的给微软的依赖注入框架写一些扩展方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: gRPC in ASP.NET Core
- 下一篇: 将 ASP.NET Core 2.1 升