Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alternate Enum Generation strategy #15

Open
justinoverton opened this issue Apr 16, 2020 · 1 comment
Open

Alternate Enum Generation strategy #15

justinoverton opened this issue Apr 16, 2020 · 1 comment
Labels
enhancement New feature or request

Comments

@justinoverton
Copy link

After the enum generation is completed I would be willing to make this change.

I have to work with XML files provided by vendors that define the enumeration restriction for fields that change somewhat often. This issue is what lead me to find LinqToXsdCore. When an xml enumeration is compiled into a .net enum, it cannot handle XML that comes across with a different value than specified in the schema.

Semantically, the schema says it is invalid. Treating enums as strings solves this, but the reality is that the generated enums are really helpful when producing input to a vendor. They may be useful when consuming a document, but also may never be looked at again.

I like LinqToXsdCore because I can load a document, look at only the sections I need, and save it. If the vendor added entirely new elements without telling me, it works fine in the round-trip.

I can't be the only one that's had this kind of issue with the strict enums and vendor controlled formats. I thought it might be worth while to look into a flexible enumeration strategy instead of compiled enums.

See: https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/enumeration-classes-over-enum-types

This defines a Enumeration that is integral with a name (just like regular enums), but for many XML restrictions it probably doesn't even need the integral part.

Code snippets from the above link:

public abstract class Enumeration : IComparable
{
    public string Name { get; private set; }

    public int Id { get; private set; }

    protected Enumeration(int id, string name)
    {
        Id = id;
        Name = name;
    }

    public override string ToString() => Name;

    public static IEnumerable<T> GetAll<T>() where T : Enumeration
    {
        var fields = typeof(T).GetFields(BindingFlags.Public |
                                         BindingFlags.Static |
                                         BindingFlags.DeclaredOnly);

        return fields.Select(f => f.GetValue(null)).Cast<T>();
    }

    public override bool Equals(object obj)
    {
        var otherValue = obj as Enumeration;

        if (otherValue == null)
            return false;

        var typeMatches = GetType().Equals(obj.GetType());
        var valueMatches = Id.Equals(otherValue.Id);

        return typeMatches && valueMatches;
    }

    public int CompareTo(object other) => Id.CompareTo(((Enumeration)other).Id);

    // Other utility methods ...
}

public class CardType : Enumeration
{
    public static readonly CardType Amex = new CardType(1, "Amex");
    public static readonly CardType Visa = new CardType(2, "Visa");
    public static readonly CardType MasterCard = new CardType(3, "MasterCard");

    public CardType(int id, string name)
        : base(id, name)
    {
    }
}

I was thinking about just post-processing the code dom. But after looking into the get/set accessors I decided if I can get this feature to be properly supported in this library that would be much easier.

@mamift
Copy link
Owner

mamift commented May 3, 2020

Sounds like a neat idea; but if you do decide to implement this I strongly recommend that you implement it via post-processing the generated code, so use Roslyn transformations on the return TextWriter instance given by the Generate(XmlSchemaSet schemaSet, LinqToXsdSettings settings) method in the XObjectsCoreGenerator class.

The existing code base for generating code from an XSD is so very convoluted and written in a now 13-year old style that it's hard to bug fix and re-factor. Fixing that enum issue for instance took quite a while.

@mamift mamift added the enhancement New feature or request label Nov 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants