使用NSwag生成客户端代码时嵌套类DTO命名冲突问题求解
解决方案
针对NSwag忽略外层嵌套类名导致DTO重名的问题,可通过以下三种方案解决,按易用性和可维护性排序:
方案1:自定义类型名称生成器(推荐,全局生效无需逐个修改类)
NSwag允许替换默认的类型名生成逻辑,你可以自定义生成规则,自动拼接外层嵌套类名与内层DTO名:
- 首先继承默认的
DefaultTypeNameGenerator实现自定义生成逻辑:
using Namotion.Reflection; using NJsonSchema; using NJsonSchema.Generation; namespace YourNamespace; public class NestedDtoTypeNameGenerator : DefaultTypeNameGenerator { protected override string GenerateTypeName(Type type, ITypeNameGeneratorSettings settings) { // 仅处理嵌套类,且外层类是MediatR的命令/查询容器类 if (type.IsNested && type.DeclaringType != null) { // 可根据需求调整格式:以下为SomeCommandRequest格式,要下划线的话改为$"{type.DeclaringType.Name}_{type.Name}" return $"{type.DeclaringType.Name}{type.Name}"; } // 非嵌套类走默认生成逻辑 return base.GenerateTypeName(type, settings); } }
- 注册自定义生成器:
如果是在ASP.NET Core服务中集成NSwag生成OpenAPI文档,在Program.cs中修改配置:
var builder = WebApplication.CreateBuilder(args); // 原有服务注册逻辑... builder.Services.AddOpenApiDocument(settings => { // 替换为自定义的类型名生成器 settings.TypeNameGenerator = new NestedDtoTypeNameGenerator(); // 保留你的其他NSwag配置 });
如果你是使用NSwag.MSBuild直接生成代码,可在nswag.json中指定自定义生成器的全限定名:
{ "schemaGeneratorSettings": { "typeNameGenerator": "YourNamespace.NestedDtoTypeNameGenerator, YourProjectAssemblyName" } }
替换YourNamespace、YourProjectAssemblyName为你项目对应的命名空间和程序集名称即可。
方案2:显式指定DTO的Schema名称(适合嵌套类数量较少的场景)
直接在每个嵌套的Request/Response类上添加DataContract特性,手动指定生成后的名称:
using System.Runtime.Serialization; public class SomeCommand { [DataContract(Name = "SomeCommandRequest")] public class Request : IRequest<Response> {} [DataContract(Name = "SomeCommandResponse")] public class Response {} public class Handler : IRequestHandler<Request, Response> {} }
NSwag会优先读取DataContract特性的Name值作为DTO的生成名称。
方案3:调整NSwag配置的扁平化命名规则
如果不想自定义代码,也可以在nswag.json中开启flattenInheritanceHierarchy并配合typeNameSeparator配置,不过适配性不如自定义生成器,仅作为备选方案:
{ "schemaGeneratorSettings": { "flattenInheritanceHierarchy": true, "typeNameSeparator": "_" } }
内容的提问来源于stack exchange,提问作者Michał Turczyn
相关产品推荐
相关产品推荐

