ممکن است در حین توسعهی یک برنامه، یکبار سرویسهای مدنظر را توسط قابلیت اسکن کتابخانههایی مانند Scrutor به برنامه اضافه کنید و یکبار هم به اشتباه تعدادی از آنها را دستی ثبت کنید و یا ممکن است کتابخانههای ثالثی را که مورد استفاده قرار دادهاید، دست آخر سبب ثبت بیش از اندازهی سرویسهای مشخصی شدهاند. در ادامه روش گزارشگیری از این سرویسهای تکراری ثبت شده را بررسی میکنیم.
یافتن سرویسهایی که به اشتباه بیش از یکبار ثبت شدهاند
کلاس زیر متدهایی را برای جمع آوری و گزارش سرویسهایی که تکراری ثبت شدهاند، ارائه میدهد:
متد الحاقی CountDuplicateServices که روش استفادهی از آن را در فایل Program.cs نمونهی زیر مشاهده میکنید، پس از ثبت تمام سرویسهای برنامه فراخوانی میشود، لیست ServiceTypeهای ثبت شده را استخراج کرده و تکراریها را جمع آوری میکند.
سپس متد الحاقی ReportDuplicateServices که پس از متد Build در متد Main برنامه فراخوانی میشود، این سرویسها را توسط لاگر جاری، نمایش میدهد:
برای مثال اگر سرویس فرضی IWeatherForecastService دوبار ثبت شده باشد:
با اجرای برنامه این خروجی را مشاهده خواهیم کرد:
کدهای کامل این مطلب را از اینجا میتوانید دریافت کنید: FindDuplicateServices.zip
یافتن سرویسهایی که به اشتباه بیش از یکبار ثبت شدهاند
کلاس زیر متدهایی را برای جمع آوری و گزارش سرویسهایی که تکراری ثبت شدهاند، ارائه میدهد:
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; namespace FindDuplicateServices.Utils { public static class DuplicateServicesFinder { private static List<(Type ServiceType, int RegistrationTimes)> _duplicateServices; public static IHostBuilder CountDuplicateServices(this IHostBuilder hostBuilder) { hostBuilder.ConfigureServices(services => { _duplicateServices = services.Where( serviceDescriptor => !serviceDescriptor.ServiceType.Assembly.FullName.Contains("Microsoft")) .GroupBy(serviceDescriptor => serviceDescriptor.ServiceType) .Where(g => g.Count() > 1) .Select(g => (g.Key, g.Count())) .ToList(); }); return hostBuilder; } public static IHost ReportDuplicateServices(this IHost host) { var logger = host.Services.GetRequiredService<ILogger<Program>>(); _duplicateServices.ForEach(item => logger.LogWarning($"Service Type: `{item.ServiceType}` -> Registration times: {item.RegistrationTimes}")); return host; } public static void RemoveService(this IServiceCollection services, Type serviceType) { var serviceDescriptor = services.FirstOrDefault(descriptor => descriptor.ServiceType == serviceType); if (serviceDescriptor != null) { services.Remove(serviceDescriptor); } } } }
سپس متد الحاقی ReportDuplicateServices که پس از متد Build در متد Main برنامه فراخوانی میشود، این سرویسها را توسط لاگر جاری، نمایش میدهد:
using FindDuplicateServices.Utils; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; namespace FindDuplicateServices { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().ReportDuplicateServices().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }) .CountDuplicateServices(); } }
برای مثال اگر سرویس فرضی IWeatherForecastService دوبار ثبت شده باشد:
namespace FindDuplicateServices { public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddScoped<IWeatherForecastService, WeatherForecastService>(); services.AddScoped<IWeatherForecastService, WeatherForecastService>(); }
کدهای کامل این مطلب را از اینجا میتوانید دریافت کنید: FindDuplicateServices.zip