Безопасное использование StreamReader с HttpContent.ReadAsStreamAsync () без закрытия основного потока - PullRequest
0 голосов
/ 21 июня 2019

У меня есть несколько классов Attribute, которым требуется доступ к данным в HttpContentHttpActionContext HttpRequstMessage), но у меня возникают проблемы с выбором наилучшего способа сделать это.Я подумал об использовании метода ReadAsStringAsync на HttpContent, но, похоже, мне нужен доступ к Stream, чтобы сначала установить позицию на 0.

Наивный способ, похоже, просто обернуть StreamReader вокруг базового потока с помощью оператора using, например, так:

public override void OnActionExecuting(HttpActionContext actionContext)
{
  string rawJson;
  using (StreamReader streamReader = new StreamReader(actionContext.Request.Content.ReadAsStreamAsync().Result))
  {
    streamReader.BaseStream.Position = 0;
    rawJson = streamReader.ReadToEnd();
  }
  // etc
}

Это хорошо работает для первого исполняемого атрибута, но каждый последующий исполняющий атрибут создает исключение на actionContext.Request.Content.ReadAsStreamAsync(), поскольку он был удален.

Вот альтернативные методы, которые работают, но я действительно хотел бы знать оптимальный способ сделать это.

1: Оберните StreamReader вокруг основного потока и никогда не располагайте его.

public override void OnActionExecuting(HttpActionContext actionContext)
{
  StreamReader streamReader = new StreamReader(actionContext.Request.Content.ReadAsStreamAsync().Result);
  streamReader.BaseStream.Position = 0;
  string rawJson = streamReader.ReadToEnd();     
  // etc
}

Это хорошо работает для каждого атрибута, но Я беспокоюсь, что у меня может быть утечка памяти , если я не утилизирую StreamReader.

2: Скопировать базовый потокв MemoryStream и оберните это StreamReader.

public override void OnActionExecuting(HttpActionContext actionContext)
{
    MemoryStream memoryStream = new MemoryStream();
    Stream s = actionContext.Request.Content.ReadAsStreamAsync().Result;
    s.Position = 0;
    s.CopyTo(memoryStream);
    string rawJson;
    using (StreamReader streamReader = new StreamReader(memoryStream))
    {
      streamReader.BaseStream.Position = 0;
      rawJson = streamReader.ReadToEnd();
    }
  // etc
}

Это хорошо работает для каждого атрибута, но много кода и может быть неэффективным .

3: установите позицию базового потока на 0, затем вызовите ReadAsStringAsync.

public override void OnActionExecuting(HttpActionContext actionContext)
{
  actionContext.Request.Content.ReadAsStreamAsync().Result.Position = 0;
  string rawJson = actionContext.Request.Content.ReadAsStringAsync().Result;
  // etc
}

Это хорошо работает для каждого атрибута, но может быть менее эффективным .

Итак, есть ли оптимальный способ сделать это без утечки памяти?

...