У меня есть пользовательская структура, которая выглядит следующим образом:
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 внутренне кэширует результат для этого типа.