Skip to content

[Suggestion] Add options for specifying external type proxies on class fields #310

@Deficuet

Description

@Deficuet

Currently, the proxies for an external type are not picked automatically for class/struct fields

using System.Numerics;

[GenerateSerde(ForType = typeof(Vector2))]
public partial class Vector2Proxy;

[GenerateSerde]
public partial class Test
{
    public Vector2 vec;     // Serde.ERR_DoesntImplementInterface
}

This can be solved by explicitly state proxy via SerdeMemberOptions

[GenerateSerde]
public partial class Test
{
    [SerdeMemberOptions(Proxy = typeof(Vector2Proxy))]
    public Vector2 vec;     // ok
}

But the description inflates rapidly as the type becomes complex

[GenerateSerde]
public partial class Test
{
    [SerdeMemberOptions(
        SerializeProxy = typeof(
            ArrayProxy.Ser<Vector2[], ArrayProxy.Ser<Vector2, Vector2Proxy>>
        ),
        DeserializeProxy = typeof(
            ArrayProxy.De<Vector2[], ArrayProxy.De<Vector2, Vector2Proxy>>
        )
    )]
    public Vector2[][] vec;     // ok
}

I think this is too tedious because the only unknown part is Vector2Proxy
So I hereby suggest to add or extend attribute for specifying external type proxy.

Conceptual design:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true, Inherited = true)]
#if !SRCGEN
public
#else
internal
#endif
sealed class UseProxy : Attribute
{
    public required Type ForType { get; init; }
    public required Type Proxy { get; init; }
    public SerdeUsage Usage { get; init; } = SerdeUsage.Both;    // make enum SerdeUsage public?
}

[GenerateSerde]
[UseProxy(ForType = typeof(Vector2), Proxy = typeof(Vector2Proxy))]
[UseProxy(ForType = typeof(Vector3), Proxy = typeof(Vector3Proxy2), Usage = SerdeUsage.Serialize)]
[UseProxy(ForType = typeof(Vector3), Proxy = typeof(Vector3Proxy), Usage = SerdeUsage.Deserialize)]
public partial class Test
{
    public Vector3 vec1;
    public Vector2[][] vec;
    [UseProxy(ForType = typeof(Vector3), Proxy = typeof(AnotherVector3Proxy))]
    public MapPair<Vector3, Vector2[]> vec3;
}

The attributes applied on fields have higher priority and can override the one applied on class. This also could be a replacement of proxies properties currently in member options.

FYI:

In Kotlin standard serialization library, the file-scoped annotation @UseSerializers is used to solve such problem at compile time, and SerializersModule can do similar thing but at runtime.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions