<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>P + J = t &#187; .NET</title>
	<atom:link href="http://blog.takeshik.org/category/prog/dotnet/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.takeshik.org</link>
	<description>Programming + Jiro Noodles = takeshik</description>
	<lastBuildDate>Sun, 09 May 2010 08:13:19 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>params Action[] in constructors</title>
		<link>http://blog.takeshik.org/2010/01/14/135</link>
		<comments>http://blog.takeshik.org/2010/01/14/135#comments</comments>
		<pubDate>Thu, 14 Jan 2010 14:26:25 +0000</pubDate>
		<dc:creator>takeshik</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[プログラミング]]></category>

		<guid isPermaLink="false">http://blog.takeshik.org/?p=135</guid>
		<description><![CDATA[@RSan からのリクエスト。大した内容ではないかもしれないけれども書いてみる。どうも表示が変になるので不自然な (C++ 的な？ｗ) スペースを置いてます。
都合上コードを色々参照してるけど、全て MIT License が適用されてます。まあ見られるくらいどうでもいいけれど。
前説
アプリケーションドメインをラップするコードを書いていたわけだが、AppDomainSetup.ConfigurationFile を設定する必要に駆られた。
順当にやるならばコンストラクタ (このコンストラクタは最終的に AppDomainSetup を作って低レベルのコンストラクタに引き渡している) に引数を追加してやればいいわけだが、そんなことをやってはきりがないのは確定的に明らか。そもそも「次」の引数候補がいつ出るか分からない。抜本的な思考の転換が必要とされていたわけ。
そこでふと思い出したのが、自分がかつて書いた HttpWebRequest をラップするコード。要は Get とかする度にうまいこと HttpWebRequest を裏で作ってくれるわけだけど、この HttpWebRequest をジェネレートする部分を
として公開しているわけ。これを応用しようと思いついた。以上。
Action&#60;T&#62; in constructors
とりあえず最初にコードを出してみる。…と思ったけど例のコードは色々サンプルにならない部分があるので新しく書き起こそうと思う。
例として ProcessStartInfo を挙げた。後は自分の例として HttpWebRequest、AppDomainSetup、の他に CompilerParameters とかでも適用可能だと思う。
変態なクラスしか頭に浮かばないけどご愛敬。まだまだあるはず。ランタイム外でも。
変なヘルパメソッド作らなきゃいけないのが癪。自分のコードでは怪しげな自前拡張メソッドで済ませているけど。let 欲しい。
つかいかた。
おまけ
params Action&#60; T &#62;[] だけでなく、IEnumerable&#60; Action&#60; T &#62;&#62; なオーバーロードもお好みで。LINQ との親和性の問題。params IEnumerable&#60; T &#62; 欲しい。
解説
これは簡単に言ってしまえばオブジェクト初期化子的な柔軟性を与えるわけだけれども、この設計のポイント的な部分を数点。
なぜオブジェクト初期化子ではないのか？
なぜ
ではなく
なのか。詰まるところ、オブジェクト初期化子は累積的な設定が不可能。つまり、引数とユーザ名のみを独立した引数としたコンストラクタを用意したとき (ここで最後に params Action&#60;ProcessStartInfo&#62;[] を用意するのがミソ)、つまり:
というコンストラクタを置いたときに、さらにパスワードまで設定したい時に、この設計なら
とできる。オブジェクト初期化子を使った設計の場合は、
といちいち同じ事を書かねばならない。新しいコンストラクタのオーバーロードを作って引数の少ない方から多い方へ流してやればいいというのは問題ではなくて、ここでの問題は、この設計によって、どんな設定であってもオーバーロードを必ずしも作ることなく対応することができ、また作ったとしても更なる設定でも対応可能だということである。副次的に、メソッドの呼び出し (Set～(obj) 等) も可能となる。
params であるということ
上で
というシグネチャを示したが、ここで、このオーバーロードは
という呼び出しでも当てはまる。params は空の引数を受け入れる。よってユーザはこの追加のイニシャライザ引数を (オーバーロードを別途用意することなく) 意識することなく使用できる。地味に見えて結構大きいポイント。
他には？
あとは…

単純な関数オブジェクトのシーケンスなので、どこかの static フィールドに設定を用意しておいて、それを連結したり、あるいは、設定の記述である [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://twitter.com/RSan">@RSan</a> からのリクエスト。大した内容ではないかもしれないけれども書いてみる。どうも表示が変になるので不自然な (C++ 的な？ｗ) スペースを置いてます。</p>
<p>都合上コードを色々参照してるけど、全て MIT License が適用されてます。まあ見られるくらいどうでもいいけれど。</p>
<h2>前説</h2>
<p><a href="http://github.com/takeshik/linx/blob/6026311813f55ec9cbaee6671d9d15aee92b61fc/LinxFramework/Reflection/CodeDomain.cs">アプリケーションドメインをラップするコード</a>を書いていたわけだが、<a href="http://msdn.microsoft.com/ja-jp/library/system.appdomainsetup.configurationfile.aspx">AppDomainSetup.ConfigurationFile</a> を設定する必要に駆られた。</p>
<p>順当にやるならば<a href="http://github.com/takeshik/linx/blob/6026311813f55ec9cbaee6671d9d15aee92b61fc/LinxFramework/Reflection/CodeDomain.cs#L92">コンストラクタ</a> (このコンストラクタは最終的に AppDomainSetup を作って<a href="http://github.com/takeshik/linx/blob/6026311813f55ec9cbaee6671d9d15aee92b61fc/LinxFramework/Reflection/CodeDomain.cs#L84">低レベルのコンストラクタ</a>に引き渡している) に引数を追加してやればいいわけだが、そんなことをやってはきりがないのは確定的に明らか。そもそも「次」の引数候補がいつ出るか分からない。抜本的な思考の転換が必要とされていたわけ。</p>
<p>そこでふと思い出したのが、自分がかつて書いた <a href="http://github.com/takeshik/linx/blob/master/LinxFramework/Net/HttpClient.cs">HttpWebRequest をラップするコード</a>。要は Get とかする度にうまいこと <a href="http://msdn.microsoft.com/ja-jp/library/system.net.httpwebrequest.aspx">HttpWebRequest</a> を裏で作ってくれるわけだけど、この HttpWebRequest をジェネレートする部分を</p>
<pre class="brush: c-sharp; auto-links: false;">
public Action&lt; HttpWebResponse &gt; ResponseHandler { get; set; }
</pre>
<p>として公開しているわけ。これを応用しようと思いついた。以上。</p>
<h2>Action&lt;T&gt; in constructors</h2>
<p>とりあえず最初に<a href="http://github.com/takeshik/linx/blob/master/LinxFramework/Reflection/CodeDomain.cs">コード</a>を出してみる。…と思ったけど例のコードは色々サンプルにならない部分があるので新しく書き起こそうと思う。</p>
<p>例として ProcessStartInfo を挙げた。後は自分の例として HttpWebRequest、AppDomainSetup、の他に <a href="http://msdn.microsoft.com/ja-jp/library/system.codedom.compiler.compilerparameters.aspx">CompilerParameters</a> とかでも適用可能だと思う。<br />
変態なクラスしか頭に浮かばないけどご愛敬。まだまだあるはず。ランタイム外でも。</p>
<pre class="brush: c-sharp; auto-links: false;">

public class SampleClass
{
    public SampleClass(ProcessStartInfo info)
    {
        // ...
    }

    public SampleClass(
        String name,
        params Action&lt; ProcessStartInfo &gt;[] infoInitializers
    )
        : this(_Apply(new ProcessStartInfo(name), infoInitializers))
    {
    }

    private static T _Apply&lt; T &gt;(T obj, IEnumerable&lt; Action&lt; T &gt;&gt; initializers)
    {
        foreach (var f in initializers) f(obj);
        return obj;
    }
}
</pre>
<p>変なヘルパメソッド作らなきゃいけないのが癪。<a href="http://github.com/takeshik/linx/blob/master/LinxFramework/Reflection/CodeDomain.cs#L92">自分のコード</a>では怪しげな自前拡張メソッドで済ませているけど。let 欲しい。</p>
<p>つかいかた。</p>
<pre class="brush: c-sharp; auto-links: false;">

new SampleClass(&quot;foo.exe&quot;, info =&gt; info.Arguments = &quot;123&quot;);
new SampleClass(&quot;foo.exe&quot;,
    info =&gt; info.Arguments = &quot;123&quot;,
    info =&gt; info.UserName = &quot;User&quot;
);
new SampleClass(&quot;foo.exe&quot;, info =&gt;
{
    info.Arguments = &quot;123&quot;;
    info.UserName = &quot;User&quot;;
});
</pre>
<h3>おまけ</h3>
<p>params Action&lt; T &gt;[] だけでなく、IEnumerable&lt; Action&lt; T &gt;&gt; なオーバーロードもお好みで。LINQ との親和性の問題。params IEnumerable&lt; T &gt; 欲しい。</p>
<h2>解説</h2>
<p>これは簡単に言ってしまえばオブジェクト初期化子的な柔軟性を与えるわけだけれども、この設計のポイント的な部分を数点。</p>
<h3>なぜオブジェクト初期化子ではないのか？</h3>
<p>なぜ</p>
<pre class="brush: c-sharp; auto-links: false;">

new SampleClass(new ProcessStartInfo(&quot;foo.exe&quot;)
{
    Arguments = &quot;123&quot;,
    UserName = &quot;User&quot;
});
</pre>
<p>ではなく</p>
<pre class="brush: c-sharp; auto-links: false;">

new SampleClass(&quot;foo.exe&quot;,
    info =&gt; info.Arguments = &quot;123&quot;,
    info =&gt; info.UserName = &quot;User&quot;,
);
</pre>
<p>なのか。詰まるところ、オブジェクト初期化子は累積的な設定が不可能。つまり、引数とユーザ名のみを独立した引数としたコンストラクタを用意したとき (ここで最後に params Action&lt;ProcessStartInfo&gt;[] を用意するのがミソ)、つまり:</p>
<pre class="brush: c-sharp; auto-links: false;">

public SampleClass(
    String name,
    String args,
    String user,
    params Action&lt; ProcessStartInfo &gt;[] infoInitializers
)
    : this(name, info =&gt;
      {
          info.Arguments = args;
          info.UserName = user;
      })
{
}
</pre>
<p>というコンストラクタを置いたときに、さらにパスワードまで設定したい時に、この設計なら</p>
<pre class="brush: c-sharp; auto-links: false;">

public SampleClass(String name, String args, String user, SecureString pass)
    : this(name, info, info =&gt; info.Password = password)
{
}
</pre>
<p>とできる。オブジェクト初期化子を使った設計の場合は、</p>
<pre class="brush: c-sharp; auto-links: false;">

new SampleClass(new ProcessStartInfo(&quot;foo.exe&quot;)
{
    Arguments = args,
    UserName = user,
    Password = pass,
});
</pre>
<p>といちいち同じ事を書かねばならない。新しいコンストラクタのオーバーロードを作って引数の少ない方から多い方へ流してやればいいというのは問題ではなくて、ここでの問題は、この設計によって、<strong>どんな設定であってもオーバーロードを必ずしも作ることなく対応することができ、また作ったとしても更なる設定でも対応可能だということ</strong>である。副次的に、メソッドの呼び出し (Set～(obj) 等) も可能となる。</p>
<h3>params であるということ</h3>
<p>上で</p>
<pre class="brush: c-sharp; auto-links: false;">

public SampleClass(
    String name,
    String args,
    String user,
    params Action&lt; ProcessStartInfo &gt;[] infoInitializers)
</pre>
<p>というシグネチャを示したが、ここで、このオーバーロードは</p>
<pre class="brush: c-sharp; auto-links: false;">

new SampleClass(&quot;name&quot;, &quot;args&quot;, &quot;user&quot;)
</pre>
<p>という呼び出しでも当てはまる。params は空の引数を受け入れる。よってユーザはこの追加のイニシャライザ引数を (オーバーロードを別途用意することなく) 意識することなく使用できる。地味に見えて結構大きいポイント。</p>
<h3>他には？</h3>
<p>あとは…</p>
<ul>
<li>単純な関数オブジェクトのシーケンスなので、どこかの static フィールドに設定を用意しておいて、それを連結したり、あるいは、設定の記述である IEnumerable&lt;Action&lt;T&gt;&gt; を生成する関数を用意したり、と、LINQ とかメタ的なプログラミングの手段も大いに援用できる。</li>
<li>順序を伴った動作のカプセル化なので、(特に継承元のクラスのコンストラクタを呼ぶ場合) 既に設定された値を上書きするといったことも可能。</li>
</ul>
<h2>まとめ</h2>
<p>オブジェクト初期化子も便利だけど、設定項目が多く、また何が設定される可能性があるか予測が困難であるオブジェクトの初期化はこのパターンを適用するのも面白いんじゃないの？</p>
<p>本稿ではコンストラクタに適用する例を挙げたけど、普通のメソッド設計でも十分有用に思う。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.takeshik.org/2010/01/14/135/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Reflection API における generic な型による継承関係の探索</title>
		<link>http://blog.takeshik.org/2010/01/06/127</link>
		<comments>http://blog.takeshik.org/2010/01/06/127#comments</comments>
		<pubDate>Wed, 06 Jan 2010 00:47:22 +0000</pubDate>
		<dc:creator>takeshik</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[プログラミング]]></category>

		<guid isPermaLink="false">http://blog.takeshik.org/?p=127</guid>
		<description><![CDATA[…において、開いたジェネリック型を使って継承関係をさらさらっと探索するのはどうも無理っぽい。つまり、

public class A&#60;TA&#62; { }
public class B&#60;TB&#62; : A&#60;TB&#62; { }
var a = typeof(A&#60;&#62;);
var b = typeof(B&#60;&#62;);

とあるとき、b.IsAssignableFrom(a) とか b.IsSubclassOf(a) は false となる。当然の挙動っぽい気も微妙にしないでもない？し、おかしい挙動なのかもしれない？けど、出来て欲しかったなあという気分。
typeof(A&#60;&#62;) みたいな感じで開いたジェネリック型のオブジェクトが取れるというのは面白いネタだけど一般的ではないようなのでたまーに宣伝したりしてます。
結局、次善策は b.BaseType.GetGenericTypeDefinition() == a となると思われる。これだと 1 つ上の親クラスしか見れないし、なんだかなあ、といった感じ。
ちなみに、恐らくこの記事がこの blog で初めてのプログラミングネタかと思われます。頑張ってこれからもネタ増やしていくので生暖かくこのジログを見守って頂ければこれ幸い。
]]></description>
			<content:encoded><![CDATA[<p>…において、開いたジェネリック型を使って継承関係をさらさらっと探索するのはどうも無理っぽい。つまり、<br />
<code><br />
public class A&lt;TA&gt; { }<br />
public class B&lt;TB&gt; : A&lt;TB&gt; { }<br />
var a = typeof(A&lt;&gt;);<br />
var b = typeof(B&lt;&gt;);<br />
</code><br />
とあるとき、<tt>b.IsAssignableFrom(a)</tt> とか <tt>b.IsSubclassOf(a)</tt> は <tt>false</tt> となる。当然の挙動っぽい気も微妙にしないでもない？し、おかしい挙動なのかもしれない？けど、出来て欲しかったなあという気分。</p>
<p><tt>typeof(A&lt;&gt;)</tt> みたいな感じで開いたジェネリック型のオブジェクトが取れるというのは面白いネタだけど一般的ではないようなのでたまーに宣伝したりしてます。</p>
<p>結局、次善策は <tt>b.BaseType.GetGenericTypeDefinition() == a</tt> となると思われる。これだと 1 つ上の親クラスしか見れないし、なんだかなあ、といった感じ。</p>
<p>ちなみに、恐らくこの記事がこの blog で初めてのプログラミングネタかと思われます。頑張ってこれからもネタ増やしていくので生暖かくこのジログを見守って頂ければこれ幸い。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.takeshik.org/2010/01/06/127/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
