拡張メソッドによるチェーンメソッド

ふと、MSDNマガジンの記事を読んでいたら目に付きました。ネーミングルール決めてusingで処理を入れ替えとか出来そうな気がしましたが、トリッキーなのでちょっとダメかな?(^^;

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

class Block : IDisposable
{
    static Stack<Block> stack = new Stack<Block>();

    ArrayList list = new ArrayList();
    public ArrayList List { get { return list; } }

    public Block()
    {
        stack.Push(this);
    }

    public static Block Current
    {
        get { return stack.Peek(); }
    }

#region IDisposable Members

    public void Dispose()
    {
        foreach (object o in Current.List)
            Console.WriteLine("Unmarked:" + o);
        stack.Pop();
    }

#endregion
}

static class Marker
{
    // 拡張メソッドを使ったチェーンメソッド
    public static T Mark<T>(this T target)
    {
        Block.Current.List.Add(target);
        return target;
    }
}

class Foo
{
    string key;
    public Foo(string key)
    {
        this.key = key;
    }

    public void Bar()
    {
        Console.WriteLine("Bar:" + key);
    }

    public override string ToString()
    {
        return key;
    }
}

class Program
{
    static void Main(string[] args)
    {
        using (new Block())
        {
            Foo foo1 = new Foo("foo1");
            // foo1オブジェクトをBlock内にマーク
            foo1.Mark().Bar();

            // foo2オブジェクトをBlock内にマーク
            new Foo("foo2").Mark().Bar();
        }

        // マークしたオブジェクトがスコープから外れたのでunmarkedが表示される
    }
} 

/* 結果
Bar:foo1
Bar:foo2
Unmarked:foo1
Unmarked:foo2
 */

拡張メソッドにするには静的クラスでなければならず、IDispose担当と拡張メソッド担当の2つのクラスを作る必要があるのが良くないですね・・・

ま、ちょっとしたネタということで。