OITA: Oika's Information Technological Activities

@oika 情報技術的活動日誌。

WPF DataContextを設定した直後にBinding先で値を参照する

突然ですが、以下の出力結果はどうなるでしょう?

//適当なボタン  
var button = new Button() { Width = 120, Height = 30 };  

//IsEnabledに"Used"というパスをバインド  
button.SetBinding(Button.IsEnabledProperty, new Binding("Used"));  

//Usedプロパティを持つ匿名クラスをコンテクストに  
button.DataContext = new { Used = false };    

Console.WriteLine(button.IsEnabled);    // <- true? false?  
続きを読む

C# Bitly APIで短縮URLを取得する

ひとむかし前はURL短縮サービスといえばbit.lyだったと思うんだけど、
今はいろいろあるし、以前ほど利用機会はなくなったかな。
けどAmazonのURLをamzn.toにしてくれたりするのはbit.lyが良いですね。

bitly_website

というか何気にびっくりしたんだけど、bit.lyじゃなくて
Bitlyっていうサイト名なのな。
URLもbitly.comだし。最初からそうだったっけか?

続きを読む

VisualStudio ビルド時のファイルコピー先をプロジェクト階層と違う場所にする

VisualStudio(というかMSBuildなんだけど)では、
ソースファイルでない任意のプロジェクトファイルについて
ソリューション エクスプローラーからビルドアクションを指定するときに
出力ディレクトリへのコピー有無を指定できる。

ただし、設定できるのはコピーするかどうかを決めるモードだけで、
コピー先のディレクトリを変えたりすることはできない。

例えば、以下のような構成で

Project Root\
    ├ ProjName.csproj
    ├ AClassFile.cs
    ├ bin\
    ├ obj\
    ├ Properties\
    └ img\
        └ image.jpg

image.jpgをプロジェクトに追加して、プロパティの
「出力ディレクトリにコピー」を「常にコピーする」にしてリリースビルドすると、
ファイルは bin\Release\img\image.jpg にコピーされる。

このコピー先をたとえば、 bin\Release\out\image.jpg にしたい場合。

続きを読む

C# 書式指定可能なログ出力クラスライブラリ「MeLogg」NuGet公開

おれおれロガーをNuGetで公開しましたよ。
ほぼ自分用だけどまあまあ使い勝手は良いのでなかろうか。

NuGet Gallery | MeLogg 1.0.0

どこにも宣伝してないのにすでに77もダウンロードされてる…。
全部日本語で書いてるのに、どういう層がダウンロードしていくんだw

基本的な使い方

以下のように使ってください。

//出力設定  
var setting = new LogSetting.Builder("event", @"D:\logs")  
{  
    Encoding = Encoding.UTF8,   //文字コード  
    Level = "Info",             //出力レベル  
    MaxFileCount = 10,          //保存ファイル数  
    MaxFileSize_byte = 1000000, //1ファイルの上限サイズ  
    RotatesFileByDay = false,   //日付変更時にファイルを切り替えるか  
}.Build();  
  
LogSettings.Update(setting);  
  
//使い方  
var logger = new Logger("event", "Main");  
logger.Debug("デバッグ");  //出力されない  
logger.Detail("詳細");     //出力されない  
logger.Info("情報");  
logger.Warn("警告");  
logger.Fatal("異常");  

出力形式の指定

デフォルトでは以下のようにLTSV形式で出力されます。

□t:2014/11/06 15:45:52.752 lv:Info th:9 pt:Main msg:情報  
□t:2014/11/06 15:45:52.783 lv:Warn th:9 pt:Main msg:警告  
□t:2014/11/06 15:45:52.798 lv:Fatal th:9 pt:Main msg:異常  

ILogBuilderを実装したクラスを自作することで
好きな書式で必要な情報だけ出力できる。

class MyLogBuilder : ILogBuilder  
{  
    public string BuildLog(DateTime time, string part, string level, int threadId, string body)  
    {  
        return string.Format("[{0}]{1}:{2}",  
                            time.ToString("MM/dd HH:mm:ss"),  
                            part,  
                            body);  
    }  
}  

↑これを以下のように設定

LogBuiderContainer.Builder = new MyLogBuilder();  

すると以下のように出力されるようになります。

[11/06 15:50:17]Main:情報  
[11/06 15:50:17]Main:警告  
[11/06 15:50:17]Main:異常  

簡単やろ?

XMLによる出力定義

おまけ機能。
出力設定はXMLファイルに書いて読み込ませることもできる。

conf.xml

<?xml version="1.0" encoding="utf-8" ?>  
  
<!--  
    - *name:          ログファイル種別管理名称  
    - *directory:     ログ出力ディレクトリ(絶対パス、または実行ディレクトリからの相対パス)  
    - level:          ログ出力レベル(Debug/Detail/Info/Warn/Fatal) 、既定値はDebug  
    - files:          保存ファイル数上限、既定値は10  
    - size:           ファイルサイズ上限(byte)、既定値は-1(ファイルサイズによるロテートを行わない)  
    - encoding:       ログ出力文字コード、既定値はShift_JIS  
    - daily-rotation: 日付の変更時にログファイルを切り替えるか、既定値はTrue  
  -->  
<Root>  
  <Logger name="logA" directory="C:\Foo\Bar" level="Warn" files="10" size="-1" encoding="Shift_JIS" daily-rotation="true" />  
  <Logger name="logB" directory="logs" />  
</Root>  

これを以下のように。

LogSettings.Load("conf.xml");  

あるいは、Logger要素の親要素を直接読み込ませる。

var rootElm = XElement.Load("conf.xml");  
LogSettings.Load(rootElm);  

モックと差し替える

テストのときとか、一時的にログ出力をしたくないときとか
一時的に出力先をコンソールにしたいだとか、
そういうときのために、普段はILoggerインタフェースに対して実装しておいて
中身を差し替えられるようにしておく。

たとえば何もしないロガーの実装例は以下のような感じ。

//何もしないロガークラス  
public class UnworkingLogger : ILogger  
{  
    public void Debug(string message, params object[] args)  
    {  
    }  
  
    public void Detail(string message, params object[] args)  
    {  
    }  
  
    public void Info(string message, params object[] args)  
    {  
    }  
  
    public void Warn(string message, params object[] args)  
    {  
    }  
  
    public void Fatal(string message, params object[] args)  
    {  
    }  
  
    public bool LogsDebug  
    {  
        get { return false; }  
    }  
  
    public bool LogsDetail  
    {  
        get { return false; }  
    }  
  
    public bool LogsInfo  
    {  
        get { return false; }  
    }  
  
    public bool LogsWarn  
    {  
        get { return false; }  
    }  
  
    public bool LogsFatal  
    {  
        get { return false; }  
    }  
}  

ロガーのインタフェースは、各レベルの出力メソッドと
出力可否確認プロパティだけだ。

出力可否確認のプロパティは、現在のログ出力設定で
そのレベルのログが出力実行されるかどうかを返すようにする。
たとえばデバッグ用のログが出力される状態のときだけ
ログ出力のための情報生成処理を入れたいときとかに使うためのものです。

if (logger.LogsDebug)  
{  
    var msg = makeLogMessage(); //なにか重い処理  
    logger.Debug(msg);  
}  

以上、よろしければご利用ください。