一个非常特定于Net Core的问题。我想为IServiceCollection
写一个扩展方法,它将在应用程序中进行配置。
这样做的原因(如果当前如此),某些组件(例如属性和控制器)位于单独的库中。因此,我想编写一个扩展方法,该方法将处理每个这些库的配置。 配置必须独立于主应用程序配置。
这是当前代码(由于上述原因,我不喜欢):
public void ConfigureServices(IServiceCollection services)
{
//..
services.AddMvc(options => {
// is needed for the library "filters".
options.Filters.Add(typeof(ExternalValidationActionFilterAttribute));
})
// is needed for the library "controllers"
.AddApplicationPart(typeof(ExternalController).Assembly)
.AddControllersAsServices();
//..
services.AddSingleton<ExternalControllerConfiguration>(new ExternalControllerConfiguration());
services.AddSingleton<ExternalValidationAttributeConfiguration>(new ExternalValidationAttributeConfiguration());
}
主应用程序中唯一的方法是AddMvc()
。其余代码特定于外部库。我想避免将外部库特定的逻辑与主应用程序逻辑混合在一起。理想情况下,重构代码应如下所示:
public void ConfigureServices(IServiceCollection services)
{
//..
services.AddMvc();
services.ConfigureExternalAttributes();
services.ConfigureExternalControllers();
//..
}
和
public static class ServiceCollectionExtensions
{
public static void ConfigureExternalAttributes(this IServiceCollection services)
{
// TBD: check if Mvc services added
// if not - add new, with options
// if yes - add options to existing
// options.Filters.Add(typeof(ExternalValidationActionFilterAttribute));
services.AddSingleton<ExternalValidationAttributeConfiguration>(new ExternalValidationAttributeConfiguration());
}
public static void ConfigureExternalControllers(this IServiceCollection services)
{
// TBD: check if Mvc services added
// if not - add new, with options
// if yes - add options to existing
// 1. If 'part' not present already: .AddApplicationPart(typeof(ExternalController).Assembly)
// 2. If 'AddControllersAsServices' not present already: .AddControllersAsServices();
// Else: skip
services.AddSingleton<ExternalControllerConfiguration>(new ExternalControllerConfiguration());
}
}
我的最后一个想法是转到git-hub,查看源代码并提出一些解决方案。但。是否有实现此结果的通用方法?也许微软已经想到了这一点,所以我正在尝试重新实现方向盘?
非常欢迎任何建议或代码示例。
答案 0 :(得分:2)
对于应用程序部分,您也可以使用Kirk Larkin建议的Microsoft.Extensions.DependencyInjection包在单独的库中创建自定义扩展类。
Install-Package Microsoft.Extensions.DependencyInjection
namespace Microsoft.Extensions.DependencyInjection
{
public static class ExternalConfigurationExtensions
{
public static IMvcBuilder ConfigureExternalControllers(this IMvcBuilder builder)
{
if (builder == null)
throw new ArgumentNullException(nameof(builder));
builder.AddApplicationPart(typeof(ExternalController).Assembly);
return builder;
}
}
}
services.AddMvc()
.ConfigureExternalControllers();
答案 1 :(得分:1)
在社区的帮助下,我能够完成修改。他们正在关注:
public static partial class MvcBuilderExtensions
{
public static IMvcBuilder ConfigureExternalAttributes(this IMvcBuilder builder, ExternalValidationAttributeConfiguration attributeConfiguration = null)
{
if (builder == null)
throw new ArgumentNullException(nameof(builder));
builder.Services.Configure<MvcOptions>(o => {
o.Filters.Add(typeof(ExternalValidationActionFilterAttribute));
});
// add default configuration
if (attributeConfiguration == null)
attributeConfiguration = new ExternalValidationAttributeConfiguration();
builder.Services.AddSingleton<ExternalValidationAttributeConfiguration>(attributeConfiguration);
return builder;
}
}
和
public static IMvcBuilder ConfigureExternalControllers(this IMvcBuilder builder, ExternalControllerConfiguration controllerConfiguration = null)
{
if (builder == null)
throw new ArgumentNullException(nameof(builder));
var externalControllerAssembly = typeof(ExternalController).Assembly;
builder.AddApplicationPart(externalControllerAssembly);
// Next part is optional. Is used to add controller as a service.
// see: https://github.com/aspnet/AspNetCore
// /Mvc/Mvc.Core/src/DependencyInjection/MvcCoreMvcBuilderExtensions.cs
var feature = new ControllerFeature();
builder.PartManager.PopulateFeature(feature);
foreach (var controller in feature.Controllers
.Where(w => w.Assembly == externalControllerAssembly)
.Select(c => c.AsType()))
{
builder.Services.TryAddTransient(controller, controller);
}
// builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
// add default configuration
if (controllerConfiguration == null)
controllerConfiguration = new ExternalControllerConfiguration();
builder.Services.AddSingleton<ExternalControllerConfiguration>(controllerConfiguration);
return builder;
}
我必须深入研究dotnet核心源代码,才能将控制器作为服务添加。否则一切都会顺利进行。谢谢大家!
P.S。在属性配置的情况下-可以使用其他类型的扩展名,如下所示:
public static void ConfigureExternalAttributes(this IServiceCollection services)
{
services.Configure<MvcOptions>(o => {
o.Filters.Add(typeof(ExternalValidationActionFilterAttribute));
});
services.AddSingleton<ExternalValidationAttributeConfiguration>(new ExternalValidationAttributeConfiguration());
}