Как добавить аннотации к Enums на странице $ metadata веб-API .net Odata - PullRequest
0 голосов
/ 21 сентября 2018

У меня есть веб-интерфейс odata, встроенный в .net.Страница $ metadata автоматически генерируется путем установки ODataConventionModelBuilder в событии регистрации.

У меня есть простое перечисление, которое выглядит так:

[Flags]
public enum Appliance : Int64
{
    Stove = 1,
    Washer = 2,
    Dryer = 4,
    Microwave = 8
}

Это простое перечисление выглядит так в $Страница метаданных:

<EnumType Name="Appliance" IsFlags="true" UnderlyingType="Edm.Int64">
    <Member Name="Stove" Value="1"/>
    <Member Name="Washer" Value="2"/>
    <Member Name="Dryer" Value="4"/>
    <Member Name="Microwave" Value="8"/>
</EnumType>

Однако я бы хотел, чтобы перечисление также содержало аннотации, когда оно появляется на странице $ метаданных.Так что это будет выглядеть так (обратите внимание на тег аннотации):

<EnumType Name="Appliance" IsFlags="true" UnderlyingType="Edm.Int64">
    <Member Name="Stove" Value="1">
        <Annotation String="Stove Top" Term="FooBar"/>
    </Member>
    <Member Name="Washer" Value="2">
        <Annotation String="Washing Machine" Term="FooBar"/>
    </Member>
    <Member Name="Dryer" Value="4"/>
    <Member Name="Microwave" Value="8"/>
</EnumType>

Есть ли способ объявить мое перечисление C # для создания этого вида?Если нет, есть ли способ программно манипулировать ODataConventionModelBuilder ИЛИ это EdmModel для вставки этих аннотаций?Возможно, используя атрибут в значениях перечисления c #?Спасибо.

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

Спасибо @Sam, вот последний метод, который добавляет аннотации к элементам перечисления на основе их атрибута "Description":

    private static void AddAnnotations(ref IEdmModel model, ODataConventionModelBuilder builder)
    {
        string enumName;
        string fullName;
        string memberName;
        string description;
        CustomAttributeData att;

        foreach (var enumTypeConfig in builder.EnumTypes)
        {
            foreach (var memberInfo in enumTypeConfig.ClrType.GetMembers())
            {
                if (memberInfo.CustomAttributes.Any(a => a.AttributeType.Name == "DescriptionAttribute"))
                {
                    enumName = enumTypeConfig.Name;
                    fullName = enumTypeConfig.FullName;
                    memberName = memberInfo.Name;

                    att = memberInfo.CustomAttributes.Where(a => a.AttributeType.Name == "DescriptionAttribute").Single();
                    description = att.ConstructorArguments[0].Value.ToString();

                    EdmTerm term = new EdmTerm("RESO.OData.Metadata", "StandardName", EdmCoreModel.Instance.GetString(true));  //TODO:  This will need to 1 of 2 choices depending on if Enum is standard or extended.
                    ((EdmModel)model).AddElement(term);

                    EdmEnumType enumType = (EdmEnumType)model.SchemaElements.First(e => e.FullName() == fullName);
                    var member = enumType.Members.First(c => c.Name == memberName);

                    EdmVocabularyAnnotation annotation = new EdmVocabularyAnnotation(member, term, new EdmStringConstant(description));
                    annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline);
                    ((EdmModel)model).SetVocabularyAnnotation(annotation);
                }
            }
0 голосов
/ 25 сентября 2018

@ АрдАтак Да.Вы можете вызвать API-интерфейсы ODL для добавления аннотации после получения IEdmModel от ODataConventionModelBuilder.

Например:

var builder = new ODataConventionModelBuilder();
builder.EnumType<Appliance>();
IEdmModel edmModel = builder.GetEdmModel();

// Create a customize term and add it into the model.
EdmTerm term = new EdmTerm("NS", "FooBar", EdmCoreModel.Instance.GetString(true));
((EdmModel)edmModel).AddElement(term);

var member = enumType.Members.First(c => c.Name == "Stove");

// Apply the annotation to the member with the new built term.
EdmVocabularyAnnotation annotation = new EdmVocabularyAnnotation(member, term, new EdmStringConstant("Stove Top"));
annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline); // OutOfLine can't work for the 'EnumMember'.
((EdmModel)edmModel).SetVocabularyAnnotation(annotation);

Затем вы можете получить следующий CSDL:

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
    <edmx:DataServices>
        <Schema Namespace="AnnotationEnumType.Models" xmlns="http://docs.oasis-open.org/odata/ns/edm">
            <EnumType Name="Appliance" UnderlyingType="Edm.Int64" IsFlags="true">
                <Member Name="Stove" Value="1">
                    <Annotation Term="NS.FooBar" String="Stove Top" />
                </Member>
                <Member Name="Washer" Value="2" />
                <Member Name="Dryer" Value="4" />
                <Member Name="Microwave" Value="8" />
            </EnumType>
        </Schema>
        <Schema Namespace="Default" xmlns="http://docs.oasis-open.org/odata/ns/edm">
            <EntityContainer Name="Container" />
        </Schema>
        <Schema Namespace="NS" xmlns="http://docs.oasis-open.org/odata/ns/edm">
            <Term Name="FooBar" Type="Edm.String" />
        </Schema>
    </edmx:DataServices>
</edmx:Edmx>

Надеюсь, это поможет.Пожалуйста, оставьте свои комментарии или напишите мне, если у вас есть дополнительные вопросы.Спасибо.

...