2015年7月27日月曜日
2015年3月4日水曜日
c# の attribute メモ
最近はコピペじゃないけどコピペのような多めのクラスと戦ってます。C#で楽ができないかなぁ。とあれこれ考え、最近見かけた属性を使って楽ができないかなと考えたのでした。
値をセットするのは別にいいのだけれども、それが大量にあると混乱してくるという。
値の表は存在していて、それとソースコードを逐次見比べて頑張っていたのだけれども、ソースコードにその表のような状態で書けたら混乱が少なくなるかな?って。ちょうどAttributeが目的にあってそうだったのです。
どうも属性はリフレクションを使うから遅くなるのは嫌だな、と食わず嫌いをしていたのだけれども、バグって速いのと正しくて遅いのならば後者ですわねェ、ということで下のような実験コードを書いたのでメモリ。
注力する場所が、番号と変数名書くところまで減らせたから少しは楽になったんじゃないかなと。
変数名も消したいし、型変換の余地も残したいけれども、欲張るとドツボにはまりそうなので一旦ここまで。
値をセットするのは別にいいのだけれども、それが大量にあると混乱してくるという。
値の表は存在していて、それとソースコードを逐次見比べて頑張っていたのだけれども、ソースコードにその表のような状態で書けたら混乱が少なくなるかな?って。ちょうどAttributeが目的にあってそうだったのです。
どうも属性はリフレクションを使うから遅くなるのは嫌だな、と食わず嫌いをしていたのだけれども、バグって速いのと正しくて遅いのならば後者ですわねェ、ということで下のような実験コードを書いたのでメモリ。
注力する場所が、番号と変数名書くところまで減らせたから少しは楽になったんじゃないかなと。
変数名も消したいし、型変換の余地も残したいけれども、欲張るとドツボにはまりそうなので一旦ここまで。
2015年2月1日日曜日
TextTemplate で C# のリソースを読み込む
C# のリソース文字列周り。デフォルトの Properties.Resources ではなく、独自の方法で取得する必要ができたのであります。
個々の文字を取得して返す部分はどうにかなるものの、大量のリソースを逐次やるのは困るので、T4で自動生成できないかと探したら、以下のサンプルを見つけました。
個々の文字を取得して返す部分はどうにかなるものの、大量のリソースを逐次やるのは困るので、T4で自動生成できないかと探したら、以下のサンプルを見つけました。
T4 Template でお手軽ローカリゼーション
http://www.xamlplayground.org/post/2010/11/25/Simplify-localization-with-a-T4-template.aspx
こちらを真似て、コード生成なしのresource ファイル用にしたものが以下の .tt コードになります。
実際に使う場合は、同名のResxファイル+TextTemplateファイルを用意、TextTemplate ファイルの内容へ以下のコードをコピぺ。
http://www.xamlplayground.org/post/2010/11/25/Simplify-localization-with-a-T4-template.aspx
こちらを真似て、コード生成なしのresource ファイル用にしたものが以下の .tt コードになります。
実際に使う場合は、同名のResxファイル+TextTemplateファイルを用意、TextTemplate ファイルの内容へ以下のコードをコピぺ。
// MainWindow.tt <#@ template debug="false" hostspecific="true" language="C#" #> <#@ output extension=".cs" encoding="utf-8" #> <#@ assembly name="System.Core" #> <#@ assembly name="System.Xml" #> <#@ assembly name="System.Xml.Linq" #> <#@ import namespace="System.IO" #> <#@ import namespace="System.Text.RegularExpressions" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Xml" #> <#@ import namespace="System.Xml.Linq" #> //------------------------------------------------------------------------------ //// This code was generated by a tool. // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ <# string appName = ".resources Generator Template"; string version = "1.0.0.0"; string ns = (string)System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("NamespaceHint"); string resxFileName = Path.ChangeExtension(Host.TemplateFile, ".resx"); string resxClassName = Path.GetFileNameWithoutExtension(Host.TemplateFile); string proxyClassName = string.Format("{0}ResourceProxy", resxClassName); XDocument document = XDocument.Parse(File.ReadAllText(resxFileName)); #> namespace <#=ns#> { using System.Globalization; using System.Windows.Markup; using System.ComponentModel; using System.Runtime.CompilerServices; ////// Represent a proxy class for "<#= resxClassName #>" resources /// [System.Diagnostics.DebuggerStepThroughAttribute()] [System.CodeDom.Compiler.GeneratedCode("<#= appName #>", "<#= version #>")] public class <#= proxyClassName #> : ResourceProxyBase { private global::System.ComponentModel.ComponentResourceManager _resource; ////// Initializes the "<#= proxyClassName #>" class /// public <#= proxyClassName #>() { var asm = System.Reflection.Assembly.GetExecutingAssembly(); _resource = new System.ComponentModel.ComponentResourceManager(typeof(<#= resxClassName #>)); } <# foreach(var item in document.Element("root").Elements("data")) { string name = EscapeName(item); if (item.Attributes("type").Count() == 0) { #> ///<# if (item.Elements("comment").Count() == 1) { #> /// [System.CodeDom.Compiler.GeneratedCode("<#= appName #>", "<#= version #>")] public string <#= name #> { get{return _resource.GetString("<#= name #>", ResourceCulture);} } <# } } #> } }<#+ public string EscapeName(XElement item) { string name = item.Attribute("name").Value; return Regex.Replace(name, "[^a-zA-Z0-9_]{1,1}", "_"); } #><#= item.Element("comment").Value #> <# } #> /// Gets the "<#= name #>" Property ///
これに食べさせるための resx ファイルは下図のような感じ。
食べさせた結果以下のようなファイルが作られる。
食べさせた結果以下のようなファイルが作られる。
// MainWindow.cs //------------------------------------------------------------------------------ //黙って Resx のpublic/internal クラス生成を使えと言われればそれまでなのだけど。// This code was generated by a tool. // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace Schwarzer { using System.Globalization; using System.Windows.Markup; using System.ComponentModel; using System.Runtime.CompilerServices; ////// Represent a proxy class for "MainWindow" resources /// [System.Diagnostics.DebuggerStepThroughAttribute()] [System.CodeDom.Compiler.GeneratedCode(".resources Generator Template", "1.0.0.0")] public class MainWindowResourceProxy : ResourceProxyBase { private global::System.ComponentModel.ComponentResourceManager _resource; ////// Initializes the "MainWindowResourceProxy" class /// public MainWindowResourceProxy() { var asm = System.Reflection.Assembly.GetExecutingAssembly(); _resource = new System.ComponentModel.ComponentResourceManager(typeof(MainWindow)); } ////// Gets the "Text1" Property /// [System.CodeDom.Compiler.GeneratedCode(".resources Generator Template", "1.0.0.0")] public string Text1 { get{return _resource.GetString("Text1", ResourceCulture);} } ////// Gets the "Text2" Property /// [System.CodeDom.Compiler.GeneratedCode(".resources Generator Template", "1.0.0.0")] public string Text2 { get{return _resource.GetString("Text2", ResourceCulture);} } ////// Gets the "Text3" Property /// [System.CodeDom.Compiler.GeneratedCode(".resources Generator Template", "1.0.0.0")] public string Text3 { get{return _resource.GetString("Text3", ResourceCulture);} } } }
これを WPF に表示したければ以下のような感じで。
上記を書いたソリューションはこちら。
<Window x:Class="Schwarzer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Schwarzer"
Height="150" Width="200">
<Window.Resources>
<!-- 先ほど自動生成したクラス -->
<local:MainWindowResourceProxy x:Key="ResourceProxy"/>
</Window.Resources>
<Window.Title>
<Binding Mode="OneWay" Path="Resource.Text3" Source="{StaticResource LangResoruce}"/>
</Window.Title>
<StackPanel>
<Button Content="{Binding Text1, Mode=OneWay, Source={StaticResource ResourceProxy}}" />
<Button Content="{Binding Text2, Mode=OneWay, Source={StaticResource ResourceProxy}}" />
</StackPanel>
</Window>
2015年1月27日火曜日
vcでスクリプトファイルみたいなものを、OutDirにコピーするときのカスタムビルドツール
いつも忘れるからメモ。
vc で lua とか hlsl とかを、出力フォルダにコピーするだけのカスタムビルドツールのコマンド。
vc で lua とか hlsl とかを、出力フォルダにコピーするだけのカスタムビルドツールのコマンド。
- 該当ファイルのプロパティから、項目の種類で「カスタムビルドツール」を選んで適用。
- カスタムビルドツールの設定。
- コマンドライン
xcopy "%(FullPath)" "$(OutDir)" /D /Y - 出力ファイル
$(OutDir)%(Filename)%(Extension) - リンクオブジェクト
いいえ
説明 も修正すると分りやすいはず。サブフォルダにファイルを置いてると(%Identity)が想定していたのと微妙に違うのが出てきて困った。
3/15/15 修正:
出力ファイルを
%(Filename)%(Extension)
にした状態で、ファイルを$(ProjectDir)にそのまま配置すると、循環依存していると警告される。そのままリビルドすると消される。
これを書いたときは、サブフォルダに配置してやっていたので、警告されなかった。
例: $(ProjectDir)scripts\myscript.lua
3/15/15 修正:
出力ファイルを
%(Filename)%(Extension)
にした状態で、ファイルを$(ProjectDir)にそのまま配置すると、循環依存していると警告される。そのままリビルドすると消される。
これを書いたときは、サブフォルダに配置してやっていたので、警告されなかった。
例: $(ProjectDir)scripts\myscript.lua
2014年11月25日火曜日
Winアプリで最大化したとき、端がはみ出て困っていた調べ物ノート
Win8の非クライアント領域サイズの調べ物
Aero のユーザーエクスペリエンスのために、 SM_CXPADDEDBORDER というものが増えたらしい。
…なぜ、SM_CXBORDER 系のままじゃダメだったのだろうか。
2014年11月9日日曜日
csharp の xxxx.resources ファイルの読み書きができないか調べたノート
csharp のリソースを編集する必要が出てきて、あれこれ調べたときのノート。
ResourceReader は、未知のリソースを全て列挙するような使い方らしい。
ResourceManager は、既知のリソースの該当データを読み込む使い方らしい。
ResourceManager は、既知のリソースの該当データを読み込む使い方らしい。
普通は使わないですわねぇ。csc とか ResourceManager が裏で上記のようなことをしているっぽい。
もうちょい調べもの。
2014年9月19日金曜日
variadic template と COM の QueryInterface
今のお仕事が、ATL/COM と格闘なのだけど、ATLを使いこなせない雑魚はのアカウントはこちらです。
それはともかくQueryInterface をコツコツ記述していたら、 variadic template で QueryInterface が楽に実装できないかと思ったメモ。
void にマッチしたときのコードが、MSVCでしか動かないコードな気がするけれども、__uuidof の時点で専用コードなので諦めた次第。
本当は、継承をたどってほしいのだけれども、やり方が思いつかない。
IID 比較の if 文が並ぶのを防げるだけでもまあいいのかなぁ。
黙ってATLを調べればいいのだろうけど、資料が見当たらなさが厳しすぎるのです。
BOOST.PP の方が建設的な気もしたけど、Libを追加する気力もなかったので。 Waveの方がいいのかな?
それはともかくQueryInterface をコツコツ記述していたら、 variadic template で QueryInterface が楽に実装できないかと思ったメモ。
void にマッチしたときのコードが、MSVCでしか動かないコードな気がするけれども、__uuidof の時点で専用コードなので諦めた次第。
本当は、継承をたどってほしいのだけれども、やり方が思いつかない。
IID 比較の if 文が並ぶのを防げるだけでもまあいいのかなぁ。
黙ってATLを調べればいいのだろうけど、資料が見当たらなさが厳しすぎるのです。
BOOST.PP の方が建設的な気もしたけど、Libを追加する気力もなかったので。 Waveの方がいいのかな?