Автоматический синтаксический анализ пользовательской структуры, когда Nullable - PullRequest
1 голос
/ 29 марта 2019

У меня есть пользовательская структура, которая выглядит следующим образом:

public struct Date
{
    private int _year;
    private int _month;
    private int _day;
    public Date(string myDate)
    {
        var date = DateTime.ParseExact(myDate, "yyyy-MM-dd");
        _year = date.Year;
        _month = date.Month;
        _day = date.Day;
    }
    public int Year => _year;
    public int Month => _month;
    public int Day => _day;
}

Это модель, которая может быть опубликована в моем webApi, которая выглядит следующим образом:

public class MyData
{
    public int? MyIntValue {get;set;}
    public string MyStringValue {get;set;}
    public Date? MyDateValue {get;set;}
}

где необнуляемые типы становятся обнуляемыми, поскольку они являются необязательными для этого сообщения.

Учитывая сообщение, похожее на приведенное ниже, опубликованное на моем webApi

{
    "MyIntValue": 5,
    "MyStringValue": "Hello",
    "MyDateValue": "2019-03-29"
}

Я хочу иметь возможностьвозьмите эту строку и проанализируйте ее в моей Date структуре.

Мой первый порт вызова - TypeConverter, украшающий мою Date структуру. Итак, я написал преобразователь DateConverter, который выглядит какниже.

public class DateConverter : TypeConverter
{
    public override bool CanConverterFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (value is string stringValue)
        {
            return new Date(stringValue);
        }
        return base.ConvertFrom(context, culture, value);
    }
}

И украсил мою Date структуру [TypeConverter(typeof(DateConverter))]

Это, однако, не работает.После некоторого (длительного) расследования я считаю, что это потому, что тип на модели на самом деле Nullable<T>.Так что после еще нескольких копаний я нашел NullableConverter.Модификации моего TypeConverter теперь делают его похожим на

public class DateConverter : NullableConverter
{
    public DateConverter() : base(typeof(Date?)) {}

    public override bool CanConverterFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (value is string stringValue)
        {
            return new Date(stringValue);
        }
        return base.ConvertFrom(context, culture, value);
    }
}

Теперь я вижу, как конструктор DateConverter получает сообщение (yay!) При отправке сообщения, однако я застрял в цикле, которыйв результате получается StackOverflowException, потому что, я полагаю, когда NullableConverter получает Nullable Type в своем конструкторе, он смотрит на базовый тип и разрешает его TypeConverter, если таковой имеется, и продолжает таким образом.Поскольку я установил NullableConverter в структуре Date, он постоянно разрешается до DateConverter и перемещается по кругу ...

На этом мое расследование остановилось.Я могу найти очень ценную небольшую информацию о NullableConverter сейчас или о любом реальном ее использовании в качестве TypeConverter, украшающем тип, и я уверен, что это класс, который мне нужно использовать.

Сделал ли я что-нибудьнеправильно?Я близко, но просто не совсем по горбу ... или я смотрю на совершенно неправильный аспект этого.

Мой вопрос такой:

Как я могу получить данного Json вмой WebAPI, где MyDateValue правильно проанализирован в моем пользовательском типе

NB. Модель - это сгенерированный код, и поэтому я предпочел бы не украшать элемент в моей модели (если это даже сработает, у менят пробовал).Однако, если это ЕДИНСТВЕННЫЙ способ, которым это может сработать, я представлю это изменение заинтересованным сторонам со своей стороны и посмотрю, какие у них есть выводы.

Дальнейшие исследования показывают, что если я вернусь к своему предыдущему TypeConverter (не NullableConverter) тогда CanConvertFrom вызывается и возвращает true, но ConvertFrom впоследствии не вызывается.Кроме того, кажется, что больше не вызывать CanConvertFrom.Возможно, Asp.Net внутренне кэширует результат для этого типа.

...