2011年2月6日日曜日

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


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

 
public static class XmlSerializeHelper
{
private static readonly System.Text.Encoding _encoding = System.Text.Encoding.UTF8;

private static readonly XmlWriterSettings _xmlSettings = new XmlWriterSettings
{
Encoding = _encoding,
NewLineChars = Environment.NewLine,
NewLineHandling = NewLineHandling.None,
};

public static XmlWriterSettings XmlSetting
{
get { return _xmlSettings; }
}

public static void Save<T>( string path, T o )
{
using ( StreamWriter sw = new StreamWriter( path, false, _encoding ) )
{
Save<T>( sw, o );
}
}

public static void Save<T>( StreamWriter sw, T o )
{
using ( XmlWriter writer = XmlWriter.Create( sw, _xmlSettings ) )
{
XmlSerializer xmlSerializer = new XmlSerializer( typeof( T ) );
xmlSerializer.Serialize( writer, o );
}
}

public static T Load<T>( string path )
{
using ( StreamReader sr = new StreamReader( path, _encoding ) )
{
return Load<T>( sr );
}
}

public static T Load<T>( StreamReader sr )
{
using ( XmlReader reader = XmlReader.Create( sr ) )
{
XmlSerializer xmlSerializer = new XmlSerializer( typeof( T ) );
return ( T ) xmlSerializer.Deserialize( reader );
}
}

}


使い方はこんな具合。
 
class SampleData
{
public string Name { get; set; }
public int Value { get; set; }
}

class Program
{
static void Main( string[] args )
{
List<SampleData> samples = new List<SampleData>{
new SampleData
{
Name = "Test1",
Value = 255
},
new SampleData
{
Name = "Test2",
Value = 100
}
};

/// XMLファイルに書出し
XmlSerializeHelper.Save<List<SampleData>>( "test.xml", samples );

/// XMLファイルから読込み
List<SampleData> loadedSamples = XmlSerializeHelper.Load<List<SampleData>>( "test.xml" );

foreach ( SampleData data in loadedSamples )
{
Console.WriteLine( string.Format( "{0} {1}", data.Name, data.Value ) );
}

}
}

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

C#用のスニペット


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

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


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

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



<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>prop</Title>
<Shortcut>_prop</Shortcut>
<Description>プロパティ用のスニペット</Description>
<Author></Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>viewname</ID>
<ToolTip>日本語名</ToolTip>
<Default>名前</Default>
</Literal>
<Literal>
<ID>type</ID>
<ToolTip>型</ToolTip>
<Default>string</Default>
</Literal>
<Literal>
<ID>property</ID>
<ToolTip>プロパティ名</ToolTip>
<Default>MyProperty</Default>
</Literal>
<Literal>
<ID>field</ID>
<ToolTip>フィールド名</ToolTip>
<Default>_field</Default>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[
/// <summery>$viewname$を設定/取得します。</summery>
public $type$ $property$
{
get{ return this.$field$; }
set{ this.$field$ = value; }
}
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>


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



<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>field</Title>
<Shortcut>_field</Shortcut>
<Description>フィールド用のスニペット</Description>
<Author></Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>viewname</ID>
<ToolTip>日本語名</ToolTip>
<Default>名前</Default>
</Literal>
<Literal>
<ID>type</ID>
<ToolTip>型</ToolTip>
<Default>string</Default>
</Literal>
<Literal>
<ID>field</ID>
<ToolTip>フィールド名</ToolTip>
<Default>_field</Default>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[
/// <summery>$viewname$</summery>
private $type$ $field$;
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>


クラス自動生成(_class)



<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>class</Title>
<Shortcut>_class</Shortcut>
<Description>クラス用のスニペット</Description>
<Author></Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>description</ID>
<ToolTip>クラスの説明</ToolTip>
<Default></Default>
</Literal>
<Literal>
<ID>name</ID>
<ToolTip>クラス名</ToolTip>
<Default>MyClass</Default>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[

/// <summery>
/// $description$
/// </summery>
class $name$
{
#region フィールド

#endregion

#region 初期化
/// <summery>
/// コンストラクタです。
/// </summery>
public $name$()
{}
#endregion

#region プロパティ

#endregion

#region メソッド

#endregion

}
]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>



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

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


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


Option Strict On
Option Explicit On

Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports EnvDTE90a
Imports EnvDTE100
Imports System.Diagnostics

Public Module FindAndReplace
Sub RemoveeRegionIndent()
DTE.Windows.Item("{CF2DDC32-8CAD-11D2-9302-005345000000}").Activate()
DTE.Find.Target = vsFindTarget.vsFindTargetCurrentProject
DTE.Find.FindWhat = "^.+{(\#region|\#endregion).*}$"
DTE.Find.ReplaceWith = "\1"
DTE.Find.MatchCase = False
DTE.Find.MatchWholeWord = False
DTE.Find.MatchInHiddenText = False
DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxRegExpr
DTE.Find.KeepModifiedDocumentsOpen = False
DTE.Find.FilesOfType = ""
DTE.Find.ResultsLocation = vsFindResultsLocation.vsFindResultsNone
DTE.Find.Action = vsFindAction.vsFindActionReplaceAll
If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
'Throw New System.Exception("vsFindResultNotFound")
End If
DTE.Windows.Item("{CF2DDC32-8CAD-11D2-9302-005345000000}").Close()
End Sub
End Module

2009年11月12日木曜日

rubyによるincludeを用いたクラス拡張のイディオム

rubyでよく使うincludeを用いたクラス拡張のイディオムについてのメモというかサンプル。


サンプルはTextMateのbundleを参考にしました。



module IncExt
module ClassMethods
def foo
puts "foo"
end
end

module InstanceMethods
def bar
puts "bar"
end
end

def self.included(receiver)
receiver.extend ClassMethods
receiver.send :include, InstanceMethods
end
end

class Buz
include IncExt
end

Buz.foo # => "foo"
Buz.new.bar # => "bar"

2009年9月20日日曜日

NotePad++の設定

NotePad++を導入した際のメモ。

1.本体の入手


いずれかを入手する。
NotePad++UTF8版(本家)
NotePad++ UTF8+EUC-JP/ShiftJIS対応版
ダウンロードしたらインストーラを起動してインストールする。


2.Explorerプラグインのセットアップをダウンロード


ExplorerプラグインはNotePad++にエクスプローラ風のウィンドウを表示するためのプラグイン。
以下のURLからダウンロードできる。
http://sourceforge.net/projects/npp-plugins/files/Explorer/


3.Explorerプラグインのインストール


Explorer.dllをNotePad++フォルダ(デフォルトインストールの場合、C:\Program Files\Notepad++\plugins)内のpluginsフォルダに入れる。


4.プラグイン設定


メニュー>プラグイン>Explorer>Explorer...を選択してエクスプローラが起動

メニュー>プラグイン>NppExecの中から、Show Console Dialog、Console Commands History、Follow $(CURRENT_DIRECTORY)を選択する

メニュー>プラグイン>NppExecのExecute ...に良く使うコマンドを設定してSaveする。起動はF6で行う。


5.よく使うコマンドの登録(C++)


ちょとした確認のためのプログラムを書いてコンパイルして実行するバッチを登録しておく。cppを書き溜めるフォルダに以下の内容でbuild.batを作成すると便利。
call "%VS90COMNTOOLS%vsvars32"
cl.exe /EHsc "%1"
%2.exe


F6で開いたダイアログ下部のコンボボックスが<temporally script>の状態で
cd $(CURRENT_DIRECTORY)
build.bat $(FULL_CURRENT_PATH) $(NAME_PART)
をcommand(s)に入力する。
Save ...ボタンを押しC++ Build and Runと名前を付ける。

この状態でC++ファイルを開いてコマンドを実行するとコンパイルから実行まで行ってくれる。

追記


あくまでも簡易的にコンパイル実行するために利用するものなので、以下のように一行で書き下したほうが便利。フルパスを書かなければいけないがバッチファイル不要。
"C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools\vsvars32.bat" && cl.exe /EHsc $(FULL_CURRENT_PATH) && $(NAME_PART).exe


Win7(64bit)で、VisualStudio2010の場合。
"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\Tools\vsvars32.bat" && cd "$(CURRENT_DIRECTORY)" && cl.exe /EHsc "$(FULL_CURRENT_PATH)" && "$(NAME_PART).exe"




6.よく使うコマンドの登録(Ruby)


先ほどと同じようにF6でダイアログを開きcommand(s)に
cd $(CURRENT_DIRECTORY)
ruby.exe $(FULL_CURRENT_PATH)
を入力する。
次にSave ...ボタンを押しRun as Rubyと入力しておく。

実行したRubyスクリプトを開いている状態で実行すればRubyスクリプトが起動する。


7.その他の設定


メニュー>表示>右端で折り返すをしておくと便利。

Rubyの補完候補はデフォルトでは用意されていない。以下のURLから入手。
http://pastebin.com/f4fedbb27
ダウンロードしたらruby.xmlにリネームしてNotePad++フォルダのplugins\APIsに入れる。

2009年7月26日日曜日

rubyのCOM(win32ole)を使うためのTIPS

rubyからCOMを使えるようになると便利。
使う場合に役に立ちそうなTIPSをまとめる。



どんなCOMが使えるのか調べる




require "win32ole"
WIN32OLE_TYPE.progids.each do |id|
puts id
end

これでCOMのprogidがリストアップされる。



使いたいCOMのメソッドとヘルプの表示


各COMのメソッドからヘルプ情報を取得できる(場合がある)
たとえば、IEを使うための簡単なヘルプを表示するには以下のコードを実行すればよい。



require "win32ole"
ole_name = 'InternetExplorer.Application'
obj = WIN32OLE.new(ole_name)

list = []
obj.ole_methods.each do |m|
list << [m.to_s, obj.ole_method(m.to_s).helpstring]
end

list.uniq.each do |item|
puts "== obj.#{item[0]}"
puts "#{item[1]}\n\n"
end

2009年6月27日土曜日

rdocでriを後から生成するための3ステップ

Windows版のrubyをソースからコンパイルして利用することにしたのですが、riドキュメントを生成し忘れてしまいました。

ri用のドキュメント生成を忘れたまま放置するのは非常にもったいない。簡単に生成できるのでメモを残します。



前提

  • rubyのソースコードがあること

  • rubyのインストールが終了していること

  • ruby\binにパスが通っていること(ここではC:\ruby\binとします)

ステップ1:riドキュメントの出力先を知る

まずriドキュメントを、どこに出力すればよいか知る必要あります。
コマンドラインコンソールから次のコマンドを実行してください。
ri -h

僕の環境では、次のような出力となりました。
--system Include documentation from Ruby's standard library:
C:/ruby/share/ri/1.8/system

--site Include documentation from libraries installed in site_lib:
C:/ruby/share/ri/1.8/site

--home Include documentation stored in ~/.rdoc:
C:/Documents and Settings/USERNAME/.rdoc

--gems Include documentation from RubyGems:
C:/Documents and Settings/USERNAME/.gem/ruby/1.8/doc/*/ri

C:/ruby/lib/ruby/gems/1.8/doc/*/ri

とりあえず欲しいのはsystemのドキュメントなので、以下のパスが出力先です。
C:/ruby/share/ri/1.8/system


ステップ2:rdocでriドキュメントを出力する

ri用のドキュメントは、以下のようにソースコードの位置へ移動してからrdocコマンドを使って生成します。

ここでいうソースコードとは、rubyのコアの.cファイル(string.cとかarray.cとか)を含むruby自身のソースコードを指します。

ここの例ではC:\src\ruby-1.8.7-p174にソースコードが置いていある想定です。
ポイントはステップ1で調べた出力先を--opオプションで指定している部分になります。

cd C:\src\ruby-1.8.7-p174
rdoc --ri -op C:/ruby/share/ri/1.8/system

ここまでの作業で、rubyのソースコード(.cおよび.rbファイル)からriドキュメントが生成されます。


ステップ3:riでマニュアルを読む

あとは、riの使い方です。最初は、ここで説明している基礎的なコマンドだけで十分だと思います。

書式例説明
ri クラス名ri Arrayクラスのドキュメントを参照する
ri クラス名.メソッド名ri File.basenameクラスメソッドのドキュメントを参照
ri クラス名#メソッド名ri Hash#rehashインスタンスメソッドのドキュメントを参照
ri searchキーワードri searchto_yamlキーワードで検索
ri -l参照可能な項目をリスト表示

ほかにも便利な使い方がありますが、最低これだけ知っていれば困らないかと。