XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEExtension.NetCore.AutoConfig

【DLL】自动实现配置文件的存储

公开
关注 0 Fork 0 Star 0
UTF-8
using MessagePack;

namespace XFEExtension.NetCore.AutoConfig;

internal static class MessagePackProfileSerializer
{
    private static readonly MessagePackSerializerOptions DocumentOptions = MessagePackSerializerOptions.Standard
        .WithSecurity(MessagePackSecurity.UntrustedData);

    public static byte[] Serialize(
        XFEProfile profile,
        IReadOnlyDictionary<string, Type> propertyTypes,
        IReadOnlyDictionary<string, GetValueDelegate> propertyGetters,
        int version)
    {
        var properties = new Dictionary<string, byte[]>(propertyGetters.Count, StringComparer.Ordinal);
        foreach (var property in propertyGetters)
        {
            if (!propertyTypes.TryGetValue(property.Key, out var propertyType))
                throw new InvalidOperationException($"未找到配置属性“{property.Key}”的类型信息");
            properties.Add(property.Key, MessagePackSerializer.Serialize(propertyType, property.Value(), profile.MessagePackOptions));
        }

        return MessagePackSerializer.Serialize(
            new MessagePackProfileDocument { Version = version, Properties = properties },
            DocumentOptions);
    }

    public static MessagePackProfileDocument Deserialize(ReadOnlyMemory<byte> content)
    {
        var document = MessagePackSerializer.Deserialize<MessagePackProfileDocument>(content, DocumentOptions)
            ?? throw new MessagePackSerializationException("MessagePack 配置文档为空");
        document.Properties ??= new Dictionary<string, byte[]>(StringComparer.Ordinal);
        return document;
    }

    public static void Populate(
        XFEProfile profile,
        IReadOnlyDictionary<string, byte[]> properties,
        IReadOnlyDictionary<string, Type> propertyTypes,
        IReadOnlyDictionary<string, SetValueDelegate> propertySetters)
    {
        foreach (var property in properties)
        {
            if (!propertyTypes.TryGetValue(property.Key, out var propertyType)
                || !propertySetters.TryGetValue(property.Key, out var setter))
                continue;
            setter(MessagePackSerializer.Deserialize(propertyType, property.Value, profile.MessagePackOptions));
        }
    }
}

[MessagePackObject(AllowPrivate = true)]
internal sealed class MessagePackProfileDocument
{
    [Key(0)]
    public int Version { get; set; }

    [Key(1)]
    public Dictionary<string, byte[]> Properties { get; set; } = new(StringComparer.Ordinal);
}