2011-11-09 4 views
2

私はオブジェクトグラフを作成するためのロジックを単純化できるように、C#で流暢なビルダーを書くのを最初に試みています。C#でオブジェクトグラフを作成するように流暢なビルダーを設計する

私の最初の考えは、各クラスの流暢ビルダーを作成することでした、そして、階層的にこのような巣にそれらを:

School school = SchoolBuilder.New() 
    .WithName("Whatchamatta U") 
    .AddClass(
     ClassBuilder.New() 
     .WithName("Arithmetic") 
     .WithClassNumber("101") 
     .AddStudent(
     StudentBuilder.New() 
     .WithName("John Smith") 
    ) 
     .AddStudent(
     StudentBuilder.New() 
     .WithName("Jane Smith") 
    ) 
) 
    .Save() 

これは、C#のインターフェースを使用してステートマシンとして実装するのは簡単、と理解することが非常に簡単です、コードを読み込もうとする開発者と新しいコードを作成しようとする開発者の両方( "With *" =プロパティを設定する、 "Add *" =子オブジェクトを追加する、 "Save"グラフ)、私は、開発者が次のようなDSLを読み書きする方が簡単かもしれないと考えました:

School school = SchoolBuilder.New() 
    .WithName("Whatchamatta U") 
    .AddClass() 
    .WithClassName("Arithmetic") 
    .WithClassNumber("101") 
    .AddStudent() 
     .WithStudentName("John Smith") 
    .AddStudent() 
     .WithStudentName("Jane Smith")   
    .Save() 

すべてのビルダーのメッセージが最上位の親ビルダーオブジェクトを通過しているので、階層の下を適切な子ビルダーオブジェクトにルーティングする方法を見つける必要があると思います。 Rubyではこれはmethod_missingで行うことができますが、C#でこれを実装するスマートな方法はありません。

醜い解決策は、各親がすべての潜在的な子孫オブジェクトのインタフェースを実装することです。それぞれのメソッドはその呼び出しを子にルーティングします。明らかにこれは望ましくありません。特にビルダー・クラスを階層に追加すると、コンパイル時にこれらのインターフェースを「仮想的に」実装する簡潔な方法はわかりませんが、そのインターフェースへのすべての呼び出しを傍受し、 、method_missingである。ダイナミックプロキシを使用してC#で実行時に動的にインターフェイスを実装する方法があることがわかりますが、これらのいずれもインテリセンスをサポートするとは思われません。

私の要件はa)これはインテリセンスで動作し、b)ビルダーは親を参照せずにオブジェクトを構築するために使用できます。つまり、すべてのビルダーが子ビルダーの構築を処理できるようにしたい(醜い解決策が実際に醜いことを意味する)

C#でこの2番目のルートを取る方法はありますか?それとも、これについて考えるのは間違った方法ですか?

+1

これで少し時間を費やした後、#2は、その清潔さにもかかわらず、良いアイデアだとは思わない。私はC#pseudo-mixinsのアイデアを使って「マスターコントローラー」を実装しました。各クラスには独自のビルダーミックスがあります。どのレベルで開始しても、そのレベルですべてのコマンドをルーティングできます。 ClassBuilder.new()で)。これはうまくいきましたが、ジェネリックの創造的な使用、例えば.AddClass ()。構文がかなり醜いものになります。もう一つの欠点は、あらゆる種類の名前衝突に遭遇することです。私は#1の作業をしており、ずっと簡単です。 – mikebridge

答えて

4

代わりにobject initializerという構文を使用することもできます。したがって、次のようになります。

School school = new School { 
    Name = "Watchamatta U", 
    Classes = new[] { 
     new Class { 
      Name = "Arithmetic", 
      Number = "101", 
      Students = new[] { 
       // etc. 
      } 
     } 
    } 
}; 

これはプロパティを初期化するため、オブジェクトを配列に変更することができます。

+0

'new []'(配列型を推論する)を追加し、オブジェクト初期化子を使うときにC#で省略可能なデフォルトのコンストラクタparensを省略することで、それを整理しました。 – mquander

+0

ありがとう、それは良い選択肢です---オブジェクトの初期化と新しい4.0パラメータのデフォルトは確かにこれをきれいにするでしょう。しかし、私はまだこのような流暢なインターフェイスがC#で実現可能かどうかを判断するのに苦労しています。 – mikebridge

関連する問題