使用程序集扫描注册 ASP.NET Core JsonConverter 实现

Posted

技术标签:

【中文标题】使用程序集扫描注册 ASP.NET Core JsonConverter 实现【英文标题】:Register ASP.NET Core JsonConverter implementations using assembly scan 【发布时间】:2021-09-18 04:58:53 【问题描述】:

我有很多 json 转换器,它们来自 JsonConverter<T>。它们位于各种程序集中,而不仅仅是执行程序集。

我是这样注册的:

services
  .AddControllers()
  .AddJsonOptions(o => 
    o.JsonSerializerOptions.Converters.Add(new FooJsonConverter());
    o.JsonSerializerOptions.Converters.Add(new BarJsonConverter());
    o.JsonSerializerOptions.Converters.Add(new BazJsonConverter());
    o.JsonSerializerOptions.Converters.Add(new QuxJsonConverter());
    // lots more...
  );

我宁愿动态添加它们,使用程序集扫描 - 与 AutoMapper、FluentValidation、Autofac 等一样,这样做。我查看了他们的仓库以获取秘方,但找不到。

所以我尝试了一些基本的反思:

services
  .AddControllers()
  .AddJsonOptions(o => 

    var jsonConverters =
      AppDomain.CurrentDomain
      .GetAssemblies()
      .SelectMany(x => x.ExportedTypes)
      .Where(x => x.BaseType != null && x.IsAssignableFrom(typeof(JsonConverter<>)));

    foreach (var jsonConverter in jsonConverters)
      o.JsonSerializerOptions.Converters.Add(Activator.CreateInstance(jsonConverter) as JsonConverter);

  );

但这无法启动,并抛出:

超光速 | Microsoft.AspNetCore.Hosting.Diagnostics |应用程序启动异常 Autofac.Core.DependencyResolutionException:激活 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionEndpointDataSourceFactory -> Microsoft.AspNetCore 时引发异常 .Mvc.Infrastructure.DefaultActionDescriptorCollectionProvider -> λ:Microsoft.AspNetCore.Mvc.Abstractions.IActionDescriptorProvider[] -> Microsoft.AspNetCore.Mvc.ApplicationModels.ControllerA ctionDescriptorProvider -> Microsoft.AspNetCore.Mvc.ApplicationModels.ApplicationModelFactory -> λ:Microsoft.AspNetCore.Mvc.ApplicationModels.IApplicationModelProvider[] -> Microsoft.AspNetC ore.Mvc.ApplicationModels.DefaultApplicationModelProvider -> Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DefaultModelMetadataProvider -> λ:Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.I CompositeMetadataDetailsProvider. ---> System.MissingMethodException:无法创建抽象类。 在 System.RuntimeTypeHandle.CreateInstance(RuntimeType 类型,Boolean publicOnly,Boolean wrapExceptions,Boolean& canBeCached,RuntimeMethodHandleInternal& ctor,Boolean& hasNoDefaultCtor )

注意Cannot create an abstract class。基类是抽象的,但我正在尝试激活子类。

这样做的正确方法是什么?另外,引用 AppDomain 是否合适,因为我记得在某处读过该行为在 aspnet 中发生了变化。

【问题讨论】:

【参考方案1】:

只需更改为:

var jsonConverters =
      AppDomain.CurrentDomain
      .GetAssemblies()
      .SelectMany(x => x.ExportedTypes)
      .Where(x => x.BaseType != null && x.IsAssignableTo(typeof(JsonConverter)));

【讨论】:

谢谢。你的笔记让我朝着正确的方向前进。我在下面添加了一个解决方案。【参考方案2】:

JsonConverter 满足您的条件 x =&gt; x.BaseType != null &amp;&amp; x.IsAssignableFrom(typeof(JsonConverter&lt;&gt;)。 它具有基本类型并且是可分配的。对不起;)

你总是可以检查是否输入.IsAbstract然后忽略它们。 另一种解决方案是按约定注册类(在这种情况下按名称)。我使用 Autofac,但方法相同

  builder
                .RegisterAssemblyTypes(serviceAssembly)
                .Where(t => t.Name.EndsWith("Service"))
                .AsSelf();

【讨论】:

谢谢。你的笔记让我朝着正确的方向前进。我在下面添加了一个解决方案。【参考方案3】:

这对我有用:

services.AddControllers().AddJsonOptions(o => 

  var jsonConverters =
    AppDomain.CurrentDomain
    .GetAssemblies()
    .Where(x => !x.IsDynamic)
    .SelectMany(x => x.ExportedTypes)
    .Where(x => x.BaseType != null)                           // is not Object, or an interface
    .Where(x => x.BaseType.IsGenericType)                     // must derive from JsonConverter<T>
    .Where(x => x.BaseType.BaseType == typeof(JsonConverter)) // exclude framework types

  foreach (var jsonConverter in jsonConverters) 
    var instance = Activator.CreateInstance(jsonConverter) as JsonConverter;
    o.JsonSerializerOptions.Converters.Add(instance);
  
);

我不确定是使用AppDomain.CurrentDomain 还是AssemblyLoadContext.Default,但这种方式似乎可行。

【讨论】:

以上是关于使用程序集扫描注册 ASP.NET Core JsonConverter 实现的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core MediatR错误:使用容器注册处理程序

ASP.Net Core 在运行时注册控制器

ASP.NET Core MVC 项目无法加载程序集

如何为 ASP.NET Core 注册和使用 MediatR 管道处理程序?

ASP .NET CORE 找不到带有自定义程序集的文件或程序集

asp.net Web.config中assembly注册程序集的目的