亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

復雜類型枚舉模型綁定

復雜類型枚舉模型綁定

C#
哈士奇WWW 2023-09-24 15:49:36
背景在 .NET Core 中,如果模型在其層次結構中包含任何位置并且提供的值與 .NET Core 中的名稱不完全匹配,則默認控制器模型綁定將失?。╪ull為操作參數生成值)??崭窕蚱婀值拇髮懽帜笗茐慕壎?,這對于我的 API 端點的使用者來說似乎不友好。enumenum我的解決方案我創建了一個模型綁定程序提供程序,它使用反射來確定目標綁定類型中的某個位置是否存在enum; 如果此檢查為真,它將返回一個自定義模型綁定器(通過傳遞類型構造enum),它使用正則表達式/字符串操作(粗略)來掃描請求正文中的值enum,并努力將它們解析為該enum類型中的名稱,在進行JsonConvert反序列化之前。在我看來,這個解決方案對于我想要實現的目標來說過于復雜和丑陋。我想要的是類似 JsonConvert 屬性(對于我的enum字段)的東西,它可以在綁定/反序列化期間進行此工作。Newtonsoft 的開箱即用解決方案 ( StringEnumConverter) 不會嘗試調整字符串以適合類型enum(我想是公平的),但我無法在這里擴展 Newtonsoft 的功能,因為它依賴于很多內部類(無需復制和粘貼)他們的大量代碼)。管道中是否有我遺漏的部分可以更好地利用來滿足這一需求?PS我把這個放在這里,而不是代碼審查(太理論化)或軟件工程(太具體);如果地方不對請指教。
查看完整描述

1 回答

?
ibeautiful

TA貢獻1993條經驗 獲得超6個贊

我為此使用了類型安全枚舉模式,我認為它適合您。通過 TypeSafeEnum,您可以使用 Newtonsoft 的 JsonConverter 屬性控制映射到 JSON 的內容。由于您沒有要發布的代碼,我已經構建了一個示例。


應用程序的 TypeSafeEnums 使用的基類:


public abstract class TypeSafeEnumBase

{

    protected readonly string Name;

    protected readonly int Value;


    protected TypeSafeEnumBase(int value, string name)

    {

        this.Name = name;

        this.Value = value;

    }


    public override string ToString()

    {

        return Name;

    }

}

作為 TypeSafeEnum 實現的示例類型,它通常是一個普通的 Enum,包括 Parse 和 TryParse 方法:


public sealed class BirdType : TypeSafeEnumBase

{

    private const int BlueBirdId = 1;

    private const int RedBirdId = 2;

    private const int GreenBirdId = 3;

    public static readonly BirdType BlueBird = 

        new BirdType(BlueBirdId, nameof(BlueBird), "Blue Bird");

    public static readonly BirdType RedBird = 

        new BirdType(RedBirdId, nameof(RedBird), "Red Bird");

    public static readonly BirdType GreenBird = 

        new BirdType(GreenBirdId, nameof(GreenBird), "Green Bird");


    private BirdType(int value, string name, string displayName) :

        base(value, name)

    {

        DisplayName = displayName;

    }


    public string DisplayName { get; }


    public static BirdType Parse(int value)

    {

        switch (value)

        {

            case BlueBirdId:

                return BlueBird;

            case RedBirdId:

                return RedBird;

            case GreenBirdId:

                return GreenBird;

            default:

                throw new ArgumentOutOfRangeException(nameof(value), $"Unable to parse for value, '{value}'. Not found.");

        }

    }


    public static BirdType Parse(string value)

    {

        switch (value)

        {

            case "Blue Bird":

            case nameof(BlueBird):

                return BlueBird;

            case "Red Bird":

            case nameof(RedBird):

                return RedBird;

            case "Green Bird":

            case nameof(GreenBird):

                return GreenBird;

            default:

                throw new ArgumentOutOfRangeException(nameof(value), $"Unable to parse for value, '{value}'. Not found.");

        }

    }


    public static bool TryParse(int value, out BirdType type)

    {

        try

        {

            type = Parse(value);

            return true;

        }

        catch

        {

            type = null;

            return false;

        }

    }


    public static bool TryParse(string value, out BirdType type)

    {

        try

        {

            type = Parse(value);

            return true;

        }

        catch

        {

            type = null;

            return false;

        }

    }

}

用于處理類型安全轉換的容器,因此您無需為實現的每個類型安全創建轉換器,并在實現新的類型安全枚舉時防止 TypeSafeEnumJsonConverter 發生更改:


public class TypeSafeEnumConverter

{

    public static object ConvertToTypeSafeEnum(string typeName, string value)

    {

        switch (typeName)

        {

            case "BirdType":

                return BirdType.Parse(value);

            //case "SomeOtherType": // other type safe enums

            //    return // some other type safe parse call

            default:

                return null;

        }

    }

}

實現 Newtonsoft 的 JsonConverter,它又調用我們的 TypeSafeEnumConverter


public class TypeSafeEnumJsonConverter : JsonConverter

{

    public override bool CanConvert(Type objectType)

    {

        var types = new[] { typeof(TypeSafeEnumBase) };

        return types.Any(t => t == objectType);

    }


    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)

    {

        string name = objectType.Name;

        string value = serializer.Deserialize(reader).ToString();

        return TypeSafeEnumConversion.ConvertToTypeSafeEnum(name, value); // call to our type safe converter

    }


    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)

    {

        if (value == null && serializer.NullValueHandling == NullValueHandling.Ignore)

        {

            return;

        }

        writer.WriteValue(value?.ToString());

    }

}

使用 BirdType 并設置要使用的轉換器的示例對象:


public class BirdCoup

{

    [JsonProperty("bird-a")]

    [JsonConverter(typeof(TypeSafeEnumJsonConverter))] // sets the converter used for this type

    public BirdType BirdA { get; set; }


    [JsonProperty("bird-b")]

    [JsonConverter(typeof(TypeSafeEnumJsonConverter))] // sets the converter for this type

    public BirdType BirdB { get; set; }

}

使用示例:


// sample #1, converts value with spaces to BirdTyp

string sampleJson_1 = "{\"bird-a\":\"Red Bird\",\"bird-b\":\"Blue Bird\"}";

BirdCoup resultSample_1 = 

JsonConvert.DeserializeObject<BirdCoup>(sampleJson_1, new JsonConverter[]{new TypeSafeEnumJsonConverter()});


// sample #2, converts value with no spaces in name to BirdType

string sampleJson_2 = "{\"bird-a\":\"RedBird\",\"bird-b\":\"BlueBird\"}";

BirdCoup resultSample_2 = 

JsonConvert.DeserializeObject<BirdCoup>(sampleJson_2, new JsonConverter[] { new TypeSafeEnumJsonConverter() });



查看完整回答
反對 回復 2023-09-24
  • 1 回答
  • 0 關注
  • 147 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號