2011年2月6日日曜日

C#でXmlシリアライズ/デシリアライズするヘルパー


C#でpublicなプロパティやフィールドをXMLにダンプするモジュールを作りまりた。
コードが横に長くてすみません。めんどくさいのでそのままにします。

  1.    
  2. public static class XmlSerializeHelper    
  3. {  
  4.     private static readonly System.Text.Encoding _encoding = System.Text.Encoding.UTF8;  
  5.   
  6.     private static readonly XmlWriterSettings _xmlSettings = new XmlWriterSettings  
  7.     {  
  8.         Encoding = _encoding,  
  9.         NewLineChars = Environment.NewLine,  
  10.         NewLineHandling = NewLineHandling.None,  
  11.     };  
  12.   
  13.     public static XmlWriterSettings XmlSetting  
  14.     {  
  15.         get { return _xmlSettings; }  
  16.     }  
  17.   
  18.     public static void Save<T>( string path, T o )  
  19.     {  
  20.         using ( StreamWriter sw = new StreamWriter( path, false, _encoding ) )  
  21.         {  
  22.             Save<T>( sw, o );  
  23.         }  
  24.     }  
  25.   
  26.     public static void Save<T>( StreamWriter sw, T o )  
  27.     {  
  28.         using ( XmlWriter writer = XmlWriter.Create( sw, _xmlSettings ) )  
  29.         {  
  30.             XmlSerializer xmlSerializer = new XmlSerializer( typeof( T ) );  
  31.             xmlSerializer.Serialize( writer, o );  
  32.         }  
  33.     }  
  34.   
  35.     public static T Load<T>( string path )  
  36.     {  
  37.         using ( StreamReader sr = new StreamReader( path, _encoding ) )  
  38.         {  
  39.             return Load<T>( sr );  
  40.         }  
  41.     }  
  42.   
  43.     public static T Load<T>( StreamReader sr )  
  44.     {  
  45.         using ( XmlReader reader = XmlReader.Create( sr ) )  
  46.         {  
  47.             XmlSerializer xmlSerializer = new XmlSerializer( typeof( T ) );  
  48.             return ( T ) xmlSerializer.Deserialize( reader );  
  49.         }  
  50.     }  
  51.   
  52. }  

使い方はこんな具合。
  1. class SampleData  
  2. {  
  3.     public string Name { getset; }  
  4.     public int Value { getset; }  
  5. }  
  6.   
  7. class Program  
  8. {  
  9.     static void Main( string[] args )  
  10.     {  
  11.         List<SampleData> samples = new List<SampleData>{  
  12.             new SampleData  
  13.             {  
  14.                 Name = "Test1",  
  15.                 Value = 255  
  16.             },  
  17.             new SampleData  
  18.             {  
  19.                 Name = "Test2",  
  20.                 Value = 100  
  21.             }  
  22.         };  
  23.   
  24.         /// XMLファイルに書出し  
  25.         XmlSerializeHelper.Save<List<SampleData>>( "test.xml", samples );  
  26.   
  27.         /// XMLファイルから読込み  
  28.         List<SampleData> loadedSamples = XmlSerializeHelper.Load<List<SampleData>>( "test.xml" );  
  29.   
  30.         foreach ( SampleData data in loadedSamples )  
  31.         {  
  32.             Console.WriteLine( string.Format( "{0} {1}", data.Name, data.Value ) );  
  33.         }  
  34.   
  35.     }  
  36. }  

なおDictionaryをダンプするには、ISerializerインターフェイスを実装する独自クラスが必要。
こちらのサイトが参考になります。

C#用のスニペット


VisualStudio用のスニペットを作ってみた。
まず下記のXMLを適当なフォルダに適当なファイル名(拡張子は.snippet)で保存する。
次にツール(T)>コードスニペットマネージャ(T)...からフォルダを指定して追加。
あとは、下記の一覧のショートカット(アンダースコア含む)をエディタ上で入力して、Tabキーを押せば補完できる。

ショートカット説明
_propプロパティ自動生成
_fieldフィールド自動生成
_classクラス自動生成


以下、フィルに保存するXML。ちょっと読めば雰囲気でカスタマイズ可能な内容。

プロパティ自動生成(_prop)


  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">  
  3.  <CodeSnippet Format="1.0.0">  
  4.   <Header>  
  5.    <Title>prop</Title>  
  6.       <Shortcut>_prop</Shortcut>  
  7.    <Description>プロパティ用のスニペット</Description>  
  8.    <Author></Author>  
  9.    <SnippetTypes>  
  10.     <SnippetType>Expansion</SnippetType>  
  11.    </SnippetTypes>  
  12.   </Header>  
  13.   <Snippet>  
  14.    <Declarations>  
  15.     <Literal>  
  16.      <ID>viewname</ID>  
  17.      <ToolTip>日本語名</ToolTip>  
  18.      <Default>名前</Default>  
  19.     </Literal>  
  20.     <Literal>  
  21.      <ID>type</ID>  
  22.      <ToolTip></ToolTip>  
  23.      <Default>string</Default>  
  24.     </Literal>  
  25.     <Literal>  
  26.      <ID>property</ID>  
  27.      <ToolTip>プロパティ名</ToolTip>  
  28.      <Default>MyProperty</Default>  
  29.     </Literal>  
  30.     <Literal>  
  31.      <ID>field</ID>  
  32.      <ToolTip>フィールド名</ToolTip>  
  33.      <Default>_field</Default>  
  34.     </Literal>  
  35.    </Declarations>  
  36.    <Code Language="csharp">  
  37.       <![CDATA[ 
  38.         /// <summery>$viewname$を設定/取得します。</summery> 
  39.         public $type$ $property$  
  40.         {  
  41.           get{ return this.$field$; } 
  42.           set{ this.$field$ = value; } 
  43.         } 
  44.    $end$]]>  
  45.    </Code>  
  46.   </Snippet>  
  47.  </CodeSnippet>  
  48. </CodeSnippets>  


フィールド自動生成(_field)


  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">  
  3.  <CodeSnippet Format="1.0.0">  
  4.   <Header>  
  5.    <Title>field</Title>  
  6.       <Shortcut>_field</Shortcut>  
  7.    <Description>フィールド用のスニペット</Description>  
  8.    <Author></Author>  
  9.    <SnippetTypes>  
  10.     <SnippetType>Expansion</SnippetType>  
  11.    </SnippetTypes>  
  12.   </Header>  
  13.   <Snippet>  
  14.    <Declarations>  
  15.     <Literal>  
  16.      <ID>viewname</ID>  
  17.      <ToolTip>日本語名</ToolTip>  
  18.      <Default>名前</Default>  
  19.     </Literal>  
  20.     <Literal>  
  21.      <ID>type</ID>  
  22.      <ToolTip></ToolTip>  
  23.      <Default>string</Default>  
  24.     </Literal>  
  25.     <Literal>  
  26.      <ID>field</ID>  
  27.      <ToolTip>フィールド名</ToolTip>  
  28.      <Default>_field</Default>  
  29.     </Literal>  
  30.    </Declarations>  
  31.    <Code Language="csharp">  
  32.       <![CDATA[ 
  33.         /// <summery>$viewname$</summery> 
  34.         private $type$ $field$; 
  35.    $end$]]>  
  36.    </Code>  
  37.   </Snippet>  
  38.  </CodeSnippet>  
  39. </CodeSnippets>  


クラス自動生成(_class)


  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">  
  3.  <CodeSnippet Format="1.0.0">  
  4.   <Header>  
  5.    <Title>class</Title>  
  6.    <Shortcut>_class</Shortcut>  
  7.    <Description>クラス用のスニペット</Description>  
  8.    <Author></Author>  
  9.    <SnippetTypes>  
  10.     <SnippetType>Expansion</SnippetType>  
  11.    </SnippetTypes>  
  12.   </Header>  
  13.   <Snippet>  
  14.    <Declarations>  
  15.     <Literal>  
  16.      <ID>description</ID>  
  17.      <ToolTip>クラスの説明</ToolTip>  
  18.      <Default></Default>  
  19.     </Literal>  
  20.     <Literal>  
  21.      <ID>name</ID>  
  22.      <ToolTip>クラス名</ToolTip>  
  23.      <Default>MyClass</Default>  
  24.     </Literal>  
  25.    </Declarations>  
  26.    <Code Language="csharp">  
  27.   <![CDATA[ 
  28.  
  29.  /// <summery> 
  30.  /// $description$ 
  31.  /// </summery> 
  32.  class $name$ 
  33.  { 
  34.     #region フィールド 
  35.      
  36.     #endregion 
  37.      
  38.     #region 初期化 
  39.   /// <summery> 
  40.   /// コンストラクタです。 
  41.   /// </summery> 
  42.   public $name$() 
  43.   {} 
  44.     #endregion 
  45.  
  46.     #region プロパティ 
  47.      
  48.     #endregion 
  49.  
  50.     #region メソッド 
  51.      
  52.     #endregion 
  53.  
  54.   } 
  55.  ]]>  
  56.    </Code>  
  57.   </Snippet>  
  58.  </CodeSnippet>  
  59. </CodeSnippets>  


もちろん標準のスニペットもあるが、細かいところが合わなかったりするので、結局は自分で作ったほうがしっくりくる。

C#の#regionのインデントを削除するマクロ


VisualStudioを使ってC#をコーディングしている際に、#regionを書くとコードのインデントと揃ってしまって不快なので、力技で置換するマクロを作ってみた。

  1. Option Strict On  
  2. Option Explicit On  
  3.   
  4. Imports System  
  5. Imports EnvDTE  
  6. Imports EnvDTE80  
  7. Imports EnvDTE90  
  8. Imports EnvDTE90a  
  9. Imports EnvDTE100  
  10. Imports System.Diagnostics  
  11.   
  12. Public Module FindAndReplace  
  13.     Sub RemoveeRegionIndent()  
  14.         DTE.Windows.Item("{CF2DDC32-8CAD-11D2-9302-005345000000}").Activate()  
  15.         DTE.Find.Target = vsFindTarget.vsFindTargetCurrentProject  
  16.         DTE.Find.FindWhat = "^.+{(\#region|\#endregion).*}$"  
  17.         DTE.Find.ReplaceWith = "\1"  
  18.         DTE.Find.MatchCase = False  
  19.         DTE.Find.MatchWholeWord = False  
  20.         DTE.Find.MatchInHiddenText = False  
  21.         DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxRegExpr  
  22.         DTE.Find.KeepModifiedDocumentsOpen = False  
  23.         DTE.Find.FilesOfType = ""  
  24.         DTE.Find.ResultsLocation = vsFindResultsLocation.vsFindResultsNone  
  25.         DTE.Find.Action = vsFindAction.vsFindActionReplaceAll  
  26.         If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then  
  27.             'Throw New System.Exception("vsFindResultNotFound")  
  28.         End If  
  29.         DTE.Windows.Item("{CF2DDC32-8CAD-11D2-9302-005345000000}").Close()  
  30.     End Sub  
  31. End Module