Skip to content

Support [ConstructorShape] appearing on static factory methods #237

@AArnott

Description

@AArnott

In adopting PolyType to our first VS feature, several types are (propery-less) singletons (typically one case in a union) and having to deal with that typically requires a custom converter and/or surrogate. It would be a lot easier if I could tack on an attribute on a factory method and be done with it.

Here's an example type. IValueValidator is a union and this class is one of the union cases.

internal class AlwaysValidValidator : IValueValidator
{
    private AlwaysValidValidator() { }

    public static AlwaysValidValidator Instance { get; } = new AlwaysValidValidator();

    public bool IsValidValue(IStoreValue value) => true;

    public bool IsValidValue(IStoreValue value, out string errorMessage)
    {
        errorMessage = string.Empty;
        return true;
    }

    public bool Equals(IValueValidator other) =>
        other is AlwaysValidValidator;
}

I can make this work with marshalers:

[TypeShape(Marshaler = typeof(Marshaler))]
internal class AlwaysValidValidator : IValueValidator
{
    private AlwaysValidValidator() { }

    public static AlwaysValidValidator Instance { get; } = new AlwaysValidValidator();

    public bool IsValidValue(IStoreValue value) => true;

    public bool IsValidValue(IStoreValue value, out string errorMessage)
    {
        errorMessage = string.Empty;
        return true;
    }

    public bool Equals(IValueValidator other) =>
        other is AlwaysValidValidator;
    internal class Marshaler : IMarshaler<AlwaysValidValidator, Marshaler.Surrogate?>
    {
        public Surrogate? Marshal(AlwaysValidValidator? value) => value is null ? null : new Surrogate();

        public AlwaysValidValidator? Unmarshal(Surrogate? value) => value is null ? null : AlwaysValidValidator.Instance;

        internal struct Surrogate
        {
        }
    }
}

But it would be much nicer if I could make it work with a static factory method:

internal class AlwaysValidValidator : IValueValidator
{
    private AlwaysValidValidator() { }

    public static AlwaysValidValidator Instance { get; } = new AlwaysValidValidator();

    [ConstructorShape]
    public static AlwaysValidValidator GetInstance() => Instance;

    public bool IsValidValue(IStoreValue value) => true;

    public bool IsValidValue(IStoreValue value, out string errorMessage)
    {
        errorMessage = string.Empty;
        return true;
    }

    public bool Equals(IValueValidator other) =>
        other is AlwaysValidValidator;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions