namespace Yes.Blog { public static class DependencyInjection { private readonly static Assembly[] Assemblies = AppDomain.CurrentDomain.GetAssemblies(); public static IServiceCollection RegisterBlogModule(this IServiceCollection services, WebApplicationBuilder builder) { var env = builder.Environment; var configuration = builder.BuildConfiguration(); services.AddConfiguration(configuration); services.AddRazorPages(); services.AddEndpoints(); services.AddViewEngine(env); services.ConfigureValidator(); services.AddAutoMapper(); services.AutoRegister(); services.AddMemoryCache(); services.AddBackgroundService(); services.AddMediatR(); services.AddHttpClient(); services.AddHttpContextAccessor(); services.AddAdminAuthentication(configuration); services.AddAuthorization(); services.AddEndpointsApiExplorer(); services.AddOpenApi(options => { options.AddDocumentTransformer((document, context, cancellationToken) => { document.Info = new() { Title = "API", Version = "V1", Description = "" }; return Task.CompletedTask; }); }); return services; } private static IConfiguration BuildConfiguration(this WebApplicationBuilder builder) { var basePath = Path.Combine(builder.Environment.ContentRootPath, "files", "config"); if (!Directory.Exists(basePath)) { Directory.CreateDirectory(basePath); } IConfiguration configuration = new ConfigurationBuilder() .SetBasePath(basePath) .AddJsonFile("appsettings.json", true, true) .AddJsonFile("appsettings.blog.json", true, true) .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true) .Build(); return configuration; } public static IServiceCollection AddConfiguration(this IServiceCollection services, IConfiguration configuration) { services.Configure(configuration); return services; } public static IServiceCollection AddBackgroundService(this IServiceCollection services) { var allAssemblies = Assembly.GetEntryAssembly()?.GetReferencedAssemblies().OrderBy(x => x.Name).Select(Assembly.Load).ToList() ?? new List(); foreach (var serviceAsm in allAssemblies) { var serviceList = serviceAsm.GetTypes().Where(t => t.IsClass && !t.IsAbstract && !t.IsInterface); foreach (Type serviceType in serviceList.Where(t => t.IsSubclassOf(typeof(BackgroundService)))) { services.AddTransient(typeof(IHostedService), serviceType); } } return services; } public static IServiceCollection AddRazorPages(this IServiceCollection services) { services.AddRazorPages(options => { options.Conventions.AuthorizeAreaFolder("Admin", "/"); options.Conventions.AllowAnonymousToAreaPage("Admin", "/Login"); }); services.Configure(option => { option.LowercaseUrls = true; option.LowercaseQueryStrings = true; }); services.AddHttpClient(); services.AddSingleton(); return services; } public static IServiceCollection AutoRegister(this IServiceCollection services) { var allAssemblies = Assembly.GetEntryAssembly()?.GetReferencedAssemblies().OrderBy(x => x.Name).Select(Assembly.Load).ToList() ?? new List(); foreach (var serviceAsm in allAssemblies) { var serviceList = serviceAsm.GetTypes().Where(t => t.IsClass && !t.IsAbstract && !t.IsInterface); foreach (Type serviceType in serviceList.Where(t => typeof(IScoped).IsAssignableFrom(t))) { var interfaceTypes = serviceType.GetInterfaces(); foreach (var interfaceType in interfaceTypes) { services.AddScoped(interfaceType, serviceType); } } foreach (Type serviceType in serviceList.Where(t => typeof(ISingleton).IsAssignableFrom(t))) { var interfaceTypes = serviceType.GetInterfaces(); foreach (var interfaceType in interfaceTypes) { services.AddSingleton(interfaceType, serviceType); } } foreach (Type serviceType in serviceList.Where(t => typeof(ITransient).IsAssignableFrom(t))) { var interfaceTypes = serviceType.GetInterfaces(); foreach (var interfaceType in interfaceTypes) { services.AddTransient(interfaceType, serviceType); } } } return services; } public static IServiceCollection AddMediatR(this IServiceCollection services) { var application = typeof(IAssembly); services.AddMediatR(configure => { configure.RegisterServicesFromAssembly(application.Assembly); }); return services; } public static IServiceCollection AddAutoMapper(this IServiceCollection services) { var typeAdapterConfig = TypeAdapterConfig.GlobalSettings; typeAdapterConfig.Scan(Assemblies); services.AddSingleton(typeAdapterConfig); services.AddScoped(); return services; } public static IServiceCollection ConfigureValidator(this IServiceCollection services) { services.AddValidatorsFromAssemblies(Assemblies); return services; } public static IServiceCollection AddViewEngine(this IServiceCollection services, IWebHostEnvironment env, Action setupAction = null) { services.AddFluid(); return services; } public static IServiceCollection AddEndpoints(this IServiceCollection services) { var assembly = typeof(IAssembly).Assembly; ServiceDescriptor[] serviceDescriptors = assembly .DefinedTypes .Where(type => type is { IsAbstract: false, IsInterface: false } && type.IsAssignableTo(typeof(IEndpoint))) .Select(type => ServiceDescriptor.Transient(typeof(IEndpoint), type)) .ToArray(); services.TryAddEnumerable(serviceDescriptors); return services; } public static IApplicationBuilder UseGlobalExceptionHandler(this WebApplication app) { app.UseMiddleware(); return app; } public static IApplicationBuilder MapEndpoints(this WebApplication app) { var apiPolicy = new AuthorizationPolicyBuilder() .AddAuthenticationSchemes(AuthenticationScheme.ApiScheme) .RequireAuthenticatedUser() .Build(); var endpoints = app.Services.GetRequiredService>().OrderByDescending(x => x.Priority); foreach (var route in endpoints) { var routeGroup = app.MapGroup($"/{route.Prefix}").WithTags(route.Tags).RequireAuthorization(); route.Map(routeGroup); } return app; } public static IApplicationBuilder UseBlogFiles(this WebApplication app, WebApplicationBuilder builder) { var uploadsPath = Path.Combine(builder.Environment.ContentRootPath, "files", "uploads"); if (!Directory.Exists(uploadsPath)) { Directory.CreateDirectory(uploadsPath); } app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider(Path.Combine(builder.Environment.ContentRootPath, "files", "uploads")), RequestPath = "/uploads", }); var themesPath = Path.Combine(builder.Environment.ContentRootPath, "files", "themes"); if (!Directory.Exists(themesPath)) { Directory.CreateDirectory(themesPath); } app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider(Path.Combine(builder.Environment.ContentRootPath, "files", "themes")), RequestPath = "/themes", }); return app; } } }