Авторест не может переопределить родительское свойство в дочернем классе - PullRequest
1 голос
/ 01 июля 2019

Я использую Autorest для генерации ssharp sdk из определения swagger 2.0, и мне интересно, возможно ли, чтобы сгенерированный дочерний класс переопределил свойство родителя с другим типом.

Пример чванства:

{
    "swagger": "2.0",
    "info": {
        "version": "1",
        "title": "My API"
    },
    "schemes": [
        "https"
    ],
    "consumes": [
        "application/json"
    ],
    "produces": [
        "application/json"
    ],
    "paths": {
        "/myResource": {
            "post": {
                "parameters": [
                    {
                        "name": "myResource_data",
                        "in": "body",
                        "schema": {
                            "$ref": "#/definitions/myResourceCreateBody"
                        },
                        "required": true
                    }
                ],
                "responses": {
                    "201": {
                        "description": "myResource response",
                        "schema": {
                            "$ref": "#/definitions/myResourceResponseExtended"
                        }
                    }
                }
            }
        }
    },
    "definitions": {
        "metaResponse": {
            "type": "object",
            "description": "Response metadata.",
            "required": [
                "api_version"
            ],
            "properties": {
                "api_version": {
                    "type": "string"
                }
            },
            "x-services": [
                "shared"
            ]
        },
        "extendedMetaResponse": {
            "allOf": [
                {
                    "$ref": "#/definitions/metaResponse"
                },
                {
                    "type": "object",
                    "properties": {
                        "myExtendedProp": {
                            "type": "string"
                        }
                    }
                }
            ],
            "x-services": [
                "shared"
            ]
        },
        "myResourceResponse": {
            "type": "object",
            "required": [
                "meta"
            ],
            "additionalProperties": false,
            "properties": {
                "meta": {
                    "$ref": "#/definitions/metaResponse"
                }
            },
            "x-services": [
                "myResource"
            ]
        },
        "myResourceResponseExtended": {
            "allOf": [
                {
                    "$ref": "#/definitions/myResourceResponse"
                },
                {
                    "type": "object",
                    "properties": {
                        "meta": {
                            "$ref": "#/definitions/extendedMetaResponse"
                        }
                    }
                }
            ],
            "x-services": [
                "myResource"
            ]
        },
        "myResourceCreateBody": {
            "type": "object",
            "required": [
                "myResource_id"
            ],
            "additionalProperties": false,
            "properties": {
                "myResource_id": {
                    "type": "string",
                    "description": "myResource identifier"
                }
            },
            "x-services": [
                "myResource"
            ]
        }
    }
}

, который генерирует следующий базовый класс C #:

    public partial class MyResourceResponse
    {
        public MyResourceResponse()
        {
            CustomInit();
        }

        public MyResourceResponse(MetaResponse meta)
        {
            Meta = meta;
            CustomInit();
        }

        partial void CustomInit();

        [JsonProperty(PropertyName = "meta")]
        public MetaResponse Meta { get; set; }

        public virtual void Validate()
        {
            if (Meta == null)
            {
                throw new ValidationException(ValidationRules.CannotBeNull, "Meta");
            }
            if (Meta != null)
            {
                Meta.Validate();
            }
        }
    }
}

И следующий дочерний класс:

    public partial class MyResourceResponseExtended : MyResourceResponse
    {
        public MyResourceResponseExtended()
        {
            CustomInit();
        }

        public MyResourceResponseExtended(MetaResponse meta)
            : base(meta)
        {
            CustomInit();
        }

        partial void CustomInit();

        public override void Validate()
        {
            base.Validate();
        }
    }

Но мой желаемый результат - иметь MyResourceResponseExtended для переопределения свойства Meta со свойством Meta типа MetaResponseExtended для раскрытия его дополнительных свойств.

Например, мой желаемый результат будет:

public partial class MyResourceResponseExtended : MyResourceResponse
{
    [JsonProperty(PropertyName = "meta")]
    public new ExtendedMetaResponse Meta { get; set; }

    public MyResourceResponseExtended(ExtendedMetaResponse meta)
        : base(meta)
    {
        Meta = meta;
        CustomInit();
    }
}

Есть ли лучший способ определить это в Swagger 2.0? Это ошибка / ограничение Autorest?

Спасибо! : -)

PS: я рассмотрел использование discriminator в файле swagger, но я либо не правильно его использую, либо он не предназначен для этой конкретной цели.

1 Ответ

1 голос
/ 01 июля 2019

Вам определенно нужно использовать discriminator и сделать из него полиморфный тип.

Чтобы иметь полиморфный тип, у вас должно быть свойство, которое вы объявляете как discriminator, и каждый тип, являющийся дочерним (то есть использующий allOf) родительского класса, должен иметь x-ms-discriminator-value что он может использовать в качестве ключа, чтобы позволить десериализатору выбрать правильный тип для десериализации.

простой пример:

swagger: '2.0'
info:
  version: 1.0.0
  title: Swagger Petstore
  license:
    name: MIT
host: petstore.swagger.io
basePath: "/v1"
schemes:
- https
consumes:
- application/json
produces:
- application/json
paths:
  "/pets":
    put:
      summary: Add a pet
      operationId: addPet
      tags:
      - pets
      parameters:
      - schema:
          "$ref": "#/definitions/Pet"
      responses:
        '200':
          description: OK
definitions:
  Pet:
    properties:
      petKind:
        type: string
      name:
        type: string
    discriminator: petKind
    required:
    - name
    - petType
  Cat:
    description: A representation of a cat
    x-ms-discriminator-value: CAT
    allOf:
    - "$ref": "#/definitions/Pet"
    - properties:
        huntingSkill:
          type: string
          description: The measured skill for hunting
          default: lazy
          enum:
          - clueless
          - lazy
          - adventurous
          - aggressive
      required:
      - huntingSkill
  Dog:
    description: A representation of a dog
    x-ms-discriminator-value: DOG
    allOf:
    - "$ref": "#/definitions/Pet"
    - properties:
        packSize:
          type: integer
          format: int32
          description: the size of the pack the dog is from
          default: 0
          minimum: 0
      required:
      - packSize

Pet объекты имеют свойство petKind (DOG или CAT), которое сообщает десериализатору, какую модель использовать для десериализации значения.

(В сгенерированном c # для этого будет использоваться атрибут класса.)

...