У меня есть требование для передачи System.Linq.Expressions.Expression
по проводам от клиента к контроллеру Web Api.
Поэтому у меня есть решение для сериализации / десериализации Expression
на основе формата JSON с использованием Serialize.Linq
.По крайней мере, в моем случае это работает достаточно быстро, и я не думаю, что это проблема.
Вот несколько классов для настройки простой демонстрации:
public class Params {
public LambdaExpression OrderBy {get;set;}
}
public class Item
{
public DateTime Date { get; set; }
}
public class ExpressionJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(Expression).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
Expression<Func<Item, DateTime>> e = o => o.Date;
return e;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var e = value as Expression;
var s = e == null ? null : "dummy text";
writer.WriteValue(s);
}
}
//the web api controller's action:
[HttpPost]
public IEnumerable<object> GetEntities(Params args)
{//<-- set break point here to debug
//…
}
Я использую Json.net
и подготовьте JsonSerializerSettings
следующим образом:
jsonSerializerSettings.DateFormatString = "yyyy-MM-ddTHH:mm:ssZ";
jsonSerializerSettings.NullValueHandling = NullValueHandling.Ignore;
jsonSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
jsonSerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
jsonSerializerSettings.Converters.Add(new PropertyInfoJsonConverter());
jsonSerializerSettings.Converters.Add(new ExpressionJsonConverter());
jsonSerializerSettings.TypeNameHandling = TypeNameHandling.Auto;
Здесь задействован один PropertyInfoJsonConverter
, но я не думаю, что это может вызвать какие-либо проблемы.Позвольте мне подробнее рассказать о проблеме.
Приведенный выше ReadJson
преобразователя возвращает просто фиктивное выражение:
Expression<Func<Item, DateTime>> e = o => o.Date;
При моей отладке это вызывает задержку около 5-7 секунд.чтобы достичь моей точки останова, установленной в действии Web Api GetEntities
(фактически без конвертера, он может сразу туда добраться).
Теперь, если я использую другое более простое выражение, подобное этому (для возвращаемого значения ReadJson
):
Expression<Func<object, DateTime>> e = o => DateTime.Now;
или даже так:
//here we don't access Date from Item, just a constant of DateTime
Expression<Func<Item, DateTime>> e = o => DateTime.Now;
Тогда он может почти мгновенно достичь точки разрыва.
Не могли бы вы обнаружить здесь что-то не так?Эта проблема заняла у меня несколько часов, чтобы диагностировать, отладить и даже погуглить, но вот что я придумал, вопрос с простой демонстрацией, заданной на SO.