[英]KnownType equivalent for discriminator on Interfaces in NSwag
當我們需要告訴 NSwag 和生成的 OpenAPI 3.0 文檔,抽象的 class 應該在客戶端轉換為某種具體類型時,我使用[KnownType]
和鑒別器並且效果很好:
using Newtonsoft.Json;
using NJsonSchema.Converters;
namespace Xyz.common.objects
{
[JsonConverter(typeof(JsonInheritanceConverter), "discriminator")]
[KnownType(typeof(DeviceTemplate))]
[KnownType(typeof(PersonelTemplate))]
public abstract class AbstractResourceTemplate
{
}
}
我遇到的問題是[KnownType]
不能在接口上使用。 所以這無法編譯:
using Newtonsoft.Json;
using NJsonSchema.Converters;
namespace Xyz.common.objects
{
[JsonConverter(typeof(JsonInheritanceConverter), "discriminator")]
[KnownType(typeof(DeviceTemplate))] // Can't put KnownType on interfaces
[KnownType(typeof(PersonelTemplate))]
public interface IResourceTemplate
{
}
}
是否有等效的代碼可以放在界面上讓 NSwag 知道區分對象應該是什么?
對於上下文,這是接口的使用方式:
public class DeviceTemplateReponse {
// In this class, Template is always going to be a DeviceTemplate, if that helps.
[WhatGoesHere???(typeof(DeviceTemplate))]
public IResourceTemplate Template { get; set; }
}
我想有一種方法可以通知 NSwag 在 DeviceTemplateReponse 中,Template 始終是具體類型 DeviceTemplate,因此不要在 OpenAPI 文檔中使用 IResourceTemplate。 這很重要,否則我會在客戶端收到此錯誤:
無法實例化抽象 class 'IResourceTemplate'。
此外,似乎TypeMapper在這里會有所幫助,但我無法找到有關如何在此處實現類似內容的文檔或示例。
我發現的一些解決方法是將接口轉換為抽象類,或者編寫我自己的僅使用具體類的對象版本。 但如果不是必須的話,我真的寧願不弄亂這樣的代碼。
接口的問題在於單個類型可以實現多個接口,但類型本身仍將實現一個公共基礎。 更重要的是,我們可以顯式重載接口屬性並為同一屬性公開多個值。
在客戶端,如果我們允許這樣做,那么接口中未定義的字段的默認值是多少? 序列化器是否應該允許所有元數據通過基類型的另一端,或者它應該被屏蔽並僅限於接口上定義的屬性。 當服務器端類型具有接口的顯式屬性時,具有不同的值,您希望將哪個值發送給客戶端,應該發送哪個值?
public interface ITest1
{
int Test { get;set; }
}
public interface ITest2
{
int Test { get;set; }
}
public class TestCase : ITest1, ITest2
{
public int Test { get;set; } = 0;
int ITest1.Test { get;set; } = 1;
int ITest2.Test { get;set; } = 2;
}
在 NSwag 中,多態性是通過直接 inheritance 來簡化和管理的,而不是通過接口的組合。 請參閱NJsonSchema - Inheritance和相關的 PR,在當前實現中僅在內部檢查直接基類型,因此您在接口定義上的屬性將被完全忽略。
它對我來說並不經常出現,出於習慣,我嘗試 map 我所有的 API 端點到該資源的特定 DTO,並且如果需要的話,不同結構有不同的端點,任何聚合端點故意使用直接 inheritance 主要是因為那是我使用的其他框架(如 EF 和 OData)的要求。
當它確實出現時,我只是創建一個實現接口的抽象 class,將它用於此端點,然后在邏輯中我們仍然可以將其轉換回去,然后它變成了一個非常小的干預。
using Newtonsoft.Json;
using NJsonSchema.Converters;
namespace Xyz.common.objects
{
public interface IResourceTemplate
{
}
[JsonConverter(typeof(JsonInheritanceConverter), "discriminator")]
[KnownType(typeof(DeviceTemplate))]
[KnownType(typeof(PersonelTemplate))]
public abstract class ResourceTemplateBase : IResourceTemplate
{
}
}
public class DeviceTemplateReponse {
[KnownType(typeof(DeviceTemplate))]
public ResourceTemplateBase Template { get; set; }
}
這很煩人嗎,嗯,是的,當它出現時......但是你可以使用隱式類型轉換或顯式輔助方法或像 AutoMapper 這樣的工具它是否足以簡化將邏輯實例設置到響應的Template
屬性中,應該對您的代碼庫的開銷非常小,您只需編寫一次。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.