2012-01-10 3 views
5

Я использую .net и должен получить некоторый текст html, поэтому я решил использовать HtmlTextWriter и StringWriter вместе, чтобы получить хорошо сформированный html. Но, несмотря на всевозможные способы написания кода, я все еще получаю предупреждения от анализатора статического кода (с использованием всех правил Microsoft). В приведенных ниже примерах кода я показываю предупреждение анализатора кода в комментарии. Чтобы упростить код, я фактически не делаю никаких вызовов в HtmlTextWriter (вы увидите комментарий к этому эффекту в каждой функции). Как я могу правильно написать код, чтобы избежать предупреждений?Как использовать StringWriter и HtmlWriter вместе без предупреждений анализа кода

// CA2000 : Microsoft.Reliability : In method 'Default.Func1()', object 'stringWriter' is not disposed along all exception paths. Call System.IDisposable.Dispose on object 'stringWriter' before all references to it are out of scope. 
public static string Func1() 
{ 
    string html; 
    StringWriter stringWriter; 
    using (var writer = new HtmlTextWriter(stringWriter = new StringWriter())) 
    { 
     // You would do some stuff with the writer here, but not for this example. 

     html = stringWriter.ToString(); 
    } 
    return html; 
} 

// CA2202 : Microsoft.Usage : Object 'stringWriter' can be disposed more than once in method 'Default.Func2()'. To avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object.: Lines: 45 
public static string Func2() 
{ 
    string html; 
    StringWriter stringWriter = null; 
    try 
    { 
     using (var writer = new HtmlTextWriter(stringWriter = new StringWriter())) 
     { 
      // You would do some stuff with the writer here, but not for this example. 

      html = stringWriter.ToString(); 
     } 
    } 
    finally 
    { 
     if (stringWriter != null) 
      stringWriter.Dispose(); 
    } 
    return html; 
} 

// CA2202 : Microsoft.Usage : Object 'stringWriter' can be disposed more than once in 
// method 'Default.Func3()'. To avoid generating a System.ObjectDisposedException 
// you should not call Dispose more than one time on an object.: Lines: 61 
public static string Func3() 
{ 
    string html; 
    using (var stringWriter = new StringWriter()) 
    { 
     using (var writer = new HtmlTextWriter(stringWriter)) 
     { 
      // You would do some stuff with the writer here, but not for this example. 

      html = stringWriter.ToString(); 
     } 
    } 
    return html; 
} 

// CA2202 : Microsoft.Usage : Object 'stringWriter' can be disposed more than once in 
// method 'Default.Func4()'. To avoid generating a System.ObjectDisposedException you 
// should not call Dispose more than one time on an object.: Lines: 77 
public static string Func4() 
{ 
    string html; 
    using (StringWriter stringWriter = new StringWriter()) 
    { 
     using (HtmlTextWriter writer = new HtmlTextWriter(stringWriter)) 
     { 
      // You would do some stuff with the writer here, but not for this example. 

      html = stringWriter.ToString(); 
     } 
    } 
    return html; 
} 

// CA2202 : Microsoft.Usage : Object 'stringWriter' can be disposed more than once in 
// method 'Default.Func5()'. To avoid generating a System.ObjectDisposedException you 
// should not call Dispose more than one time on an object.: Lines: 100 
public static string Func5() 
{ 
    string html; 
    StringWriter stringWriter = null; 
    try 
    { 
     stringWriter = new StringWriter(); 
     using (HtmlTextWriter htmlTextWriter = new HtmlTextWriter(stringWriter)) 
     { 
      // You would do some stuff with the writer here, but not for this example. 

      html = stringWriter.ToString(); 
     } 
    } 
    finally 
    { 
     if (stringWriter != null) 
      stringWriter.Dispose(); 
    } 
    return html; 
} 
+0

много интересных комментариев по поводу [CA2202] (http://msdn.microsoft.com/en-us/library/ms182334.aspx) на MSDN –

+1

К сожалению ни один из комментариев в Ссылка CA2202 выше рассмотрела предупреждение с этой конкретной парой классов, когда я их пробовал. –

+0

В [другом посте] (http://stackoverflow.com/questions/3831676/ca2202-how-to-solve-this -case), Ханс Питер пишет: «Это не совсем реальные ошибки, эти классы .NET устойчивы к несколько вызовов Dispose(). " Имея это в виду, у меня возникает соблазн сделать двойное использование, как Func3 или Func4, и подавить предупреждение CA2202. –

ответ

0

Поскольку StringWriter является одноразовым, вы можете обернуть свой внутренний писатель другим использованием.

using (StringWriter stringWriter = new StringWriter()) 
{ 
    using (var writer = new HtmlTextWriter(stringWriter)) 
    { 
     html = stringWriter.ToString(); 
    } 
} 
return html; 
+0

Это почти то же самое, что и его 'Func3()' и 'Func4()'. –

+0

@JesseC.Slicer oops my bad, не видел func3 и 4 –

+0

Я только что загрузил FXCop 10.0.30319.1 и написал небольшую тестовую упряжь, используя это, и это нормально, я не вижу никаких проблем. У меня есть предупреждение о Mark wirht StrongName, IFormatProvider, MarkAssembliesWithNeutralResourcesLanguage, но ничего об удалении. –

1

Измените Func5 быть следующим:

public static string Func5() 
{ 
    string html; 
    StringWriter stringWriter = null; 
    try 
    { 
     stringWriter = new StringWriter(); 
     using (HtmlTextWriter htmlTextWriter = new HtmlTextWriter(stringWriter)) 
     { 
      stringWriter = null; 

      // You would do some stuff with the writer here, but not for this example. 

      html = htmlTextWriter.InnerWriter.ToString(); 
     } 
    } 
    finally 
    { 
     if (stringWriter != null) 
      stringWriter.Dispose(); 
    } 
    return html; 
} 

Ключ установить переменную StringWriter к нулю (что не влияет на InnerWriter экземпляра HtmlTextWriter), а затем использовать InnerWriter. ToString(), чтобы получить HTML.

Это действительно только модифицированная версия примера в статье MSDN, упомянутая в предыдущем комментарии, но специально применяемая к вашему использованию.

1

На самом деле нет способа сделать этот код предупреждением, поскольку в данном конкретном случае анализ кода неверен.

Правильный код FUNC3, добавив атрибут CodeAnalysis.SuppressMessage:

// Code Analysis is incorrectly assuming that HtmlTextWriter.Dispose will dispose of the InnerWriter, but it actually does not. 
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")] 
public static string Func3() 
{ 
    string html; 
    using (var stringWriter = new StringWriter()) 
    { 
     using (var writer = new HtmlTextWriter(stringWriter)) 
     { 
      // You would do some stuff with the writer here, but not for this example. 

      // I prefer to use writer.InnerWriter as opposed to stringWriter for clarity. 
      html = writer.InnerWriter.ToString(); 
     } 
    } 
    return html; 
} 

Документация CA2202 использует пример StreamWriter выбывает из его потока, который является правильным, но HtmlTextWriter не выбрасывайте его внутренний TextWriter (проверяемый путем подкласса StringWriter и установка точки останова в переопределении Dispose). Это немного сбивает с толку, так как HtmlTextWriter происходит из TextWriter, а StringWriter также происходит из TextWriter (в отличие от StreamWriter и его потока, являющегося двумя совершенно разными классами), поэтому зачем HtmlTextWriter нужен InnerWriter? ... но так или иначе, так оно и работает ,

Кроме того, говорится в документации не подавить это предупреждение, потому что «Даже если Dispose для объекта, как известно, безопасно Вызываемые несколько раз, реализация может измениться в будущем.» Тем не менее, в этом случае Dispose является не вызывается несколько раз, поэтому предупреждение можно безопасно подавить.

Но не верьте мне на слово! Вот доказательство:

using System; 
using System.IO; 
using System.Web.UI; 

namespace WebApplication1 
{ 
    public partial class WebForm1 : System.Web.UI.Page 
    { 
     protected void Page_Load(object sender, EventArgs e) 
     { 
      StreamWillBeDisposed(); 
      TextWriterWillNotBeDisposed(); 
     } 

     public static void StreamWillBeDisposed() 
     { 
      Stream stream = new DebugMemoryStream(); 
      using (StreamWriter writer = new StreamWriter(stream)) 
      { 
       // Use the writer object... 
      }// Underlying Stream will be disposed here by the StreamWriter 
     } 

     public static void TextWriterWillNotBeDisposed() 
     { 
      TextWriter stringWriter = new DebugStringWriter(); 
      using (HtmlTextWriter writer = new HtmlTextWriter(stringWriter)) 
      { 
       // Use the writer object... 
      }// Underlying TextWriter will NOT be disposed here by the HtmlTextWriter 
     } 
    } 


    public class DebugMemoryStream : MemoryStream 
    { 
     protected override void Dispose(bool disposing) 
     { 
      // This Stream will be disposed when the StreamWriter is disposed 
      System.Diagnostics.Debugger.Break(); 
      base.Dispose(disposing); 
     } 
    } 

    public class DebugStringWriter : StringWriter 
    { 
     protected override void Dispose(bool disposing) 
     { 
      // This code will never see the light of day 
      System.Diagnostics.Debugger.Break(); 
      base.Dispose(disposing); 
     } 
    } 

} 

 Смежные вопросы

  • Нет связанных вопросов^_^