.Net 8 API:使用 const 序列化一类结构

问题描述 投票:0回答:1

我想要做的事情一开始可能看起来很奇怪,但我会解释为什么我要努力实现这一目标。

在我的

Domain
层中,我创建了一个常量类,在其中定义了所有
AWS DynamoDB
数据库结构,以便在需要数据库表和字段名称的地方像
Enum
一样使用。

DBStructure.cs

public class DBStructure
{
    public struct DynamoDB
    {
        public struct Tables 
        {
            public struct Tests
            {
                public const string TableName = "test_test";

                public struct Fields
                {
                    [JsonProperty("DynamoDB")]
                    public const string TestId = "test_id";
                    public const string Test = "test";
                    public const string TestLevel = "test_level";
                    public const string TestNumber = "test_level_number";
                    public const string TestType = "test_type";
                    public const string TestSubject = "test_subject";
                    public const string FP = "f_p";
                    public const string PermittedErrors = "permitted_errors";
                    public const string TimeLimit = "time_limit";
                    public const string TestCreator = "test_author";
                    public const string TestCreatorEmail = "email";
                    public const string Active = "active";
                    public const string TestComments = "comments";
                    public const string TestImage = "image";
                    public const string TestLanguage = "language_id";
                    public const string TestLanguage2 = "test_lng";
                    public const string TestLanguage3 = "test_language";
                    public const string TestTimestamp = "timestamp";
                }

                public struct Indexes
                {
                    public const string TestTypeIndex = "test_type-index";
                    public const string TestSubjectIndex = "test_subject-index";
                }
            }

            public struct Questions
            {
                public const string TableName = "test_questions";

                public struct Fields
                {
                    public const string QuestionId = "question_id";
                    public const string TestId = "test_id";
                    public const string Instructions = "instructions";
                    public const string Question = "question";
                    public const string Explanations = "explanations";
                    public const string QuestionNumber = "question_number";
                    public const string Timestamp = "timestamp";
                }

                public struct Indexes
                {
                    public const string TestIdQuestionNumberIndex = "test_id-question_number-index";
                }
            }

            ... More Structs
        }
    }
}

我需要序列化这个完整的类,以便能够通过 Ajax 调用将字符串常量传递给 Javascript。

这样做的原因是因为我需要像 JavaScript 中那样的字段和表名称,当要保存

Test
时,我创建一个 json 并将其数据(从 html 表单字段读取)发送到控制器.

我绝对知道这不是实现这一目标的方法(或者至少不是最好的方法),但我正处于一个大的重构过程中,并且只是一步一步地进行。

我已经尝试过结构是否可以序列化,但问题是在我的例子中成员是常量,所以它不起作用。

有什么方法可以完成我的类序列化吗?有什么意见欢迎留言。

.net serialization struct static constants
1个回答
0
投票

感谢: 使用 System.Text.Json.Serialization 序列化 const

我能够使用提供的

JsonExtensions
类对我的问题进行排序。

JsonExtensions

public static partial class JsonExtensions
{
    // Include opted-in constants for the specified type.
    public static Action<JsonTypeInfo> AddOptInConstMembers<TOptInAttribute>(Type type) where TOptInAttribute : System.Attribute =>
        typeInfo =>
        {
            if (typeInfo.Type == type)
                AddOptInConstMembers<TOptInAttribute>(typeInfo);
        };

    // Include opted-in constants for all types.
    public static void AddOptInConstMembers<TOptInAttribute>(JsonTypeInfo typeInfo) where TOptInAttribute : System.Attribute
    {
        if (typeInfo.Kind != JsonTypeInfoKind.Object)
            return;
        foreach (var field in typeInfo.Type.GetConstants().Where(f => Attribute.IsDefined(f, typeof(TOptInAttribute))))
        {
            var name = field.GetCustomAttribute<JsonPropertyNameAttribute>()?.Name ?? typeInfo.Options.PropertyNamingPolicy?.ConvertName(field.Name) ?? field.Name;
            var value = field.GetValue(null); // field.GetValue(null); returns enums as enums rathen raw integers.
            var propertyInfo = typeInfo.CreateJsonPropertyInfo(value?.GetType() ?? field.FieldType, name);
            propertyInfo.Get = (o) => value;
            propertyInfo.CustomConverter = field.GetCustomAttribute<JsonConverterAttribute>()?.ConverterType is { } converterType
                ? (JsonConverter?)Activator.CreateInstance(converterType)
                : null;
            typeInfo.Properties.Add(propertyInfo);
        }
    }

    static IEnumerable<FieldInfo> GetConstants(this Type type) =>
        // From the answer https://stackoverflow.com/a/10261848
        // By https://stackoverflow.com/users/601179/gdoron
        // To https://stackoverflow.com/questions/10261824/how-can-i-get-all-constants-of-a-type-by-reflection
        type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy)
        .Where(fi => fi.IsLiteral && !fi.IsInitOnly);
}

然后在我的代码中:

public class DBStructure
{
    public struct DynamoDB
    {
        public struct Tables 
        {
            public struct Tests
            {
                public const string TableName = "test_test";

                public struct Fields
                {
                    [JsonInclude]
                    public const string TestId = "test_id";
                    [JsonInclude]
                    public const string Test = "test";
                    [JsonInclude]
                    public const string TestLevel = "test_level";
                    ...
                }
            }

            public struct Questions
            {
                public const string TableName = "test_questions";

                public struct Fields
                {
                    [JsonInclude]
                    public const string QuestionId = "question_id";
                    [JsonInclude]
                    public const string TestId = "test_id";
                    ...
                }
            }

            ... More Structs
        }
    }
}

我或多或少像这样使用它(仍然需要稍微调整一下,以便返回一个包含所有 json 的对象,但我已经接近我的期望了):

var testsFiels = new DBStructure.DynamoDB.Tables.Tests.Fields();
var questionsFiels = new DBStructure.DynamoDB.Tables.Questions.Fields();

var options = new JsonSerializerOptions
{
    TypeInfoResolver = new DefaultJsonTypeInfoResolver
    {
        Modifiers = { JsonExtensions.AddOptInConstMembers<JsonIncludeAttribute> },
    },
};

var testsJson = System.Text.Json.JsonSerializer.Serialize(testsFiels, options);
var questionsJson = System.Text.Json.JsonSerializer.Serialize(questionsFiels, options);
© www.soinside.com 2019 - 2024. All rights reserved.