2013-01-09 43 views
6

Dart編程語言支持method cascades。方法級聯將實現下面的Silverlight/WPF的C#代碼:C中的模擬方法級聯#

var listBox = new ListBox(); 

listBox.Width = 200; 
listBox.MouseEnter += (s, e) => Console.WriteLine("MouseEnter"); 

var button1 = new Button() { Content = "abc" }; 
button1.Click += (s, e) => Console.WriteLine("button1.Click"); 

listBox.Items.Add(button1); 

var button2 = new Button() { Content = "def" }; 
button2.Click += (s, e) => Console.WriteLine("button2.Click"); 

listBox.Items.Add(button2); 

ContentPanel.Children.Add(listBox); 

寫入,而不是爲:

ContentPanel.Children.Add(
    new ListBox() 
     ..Width = 200 
     ..MouseEnter += ((s, e) => Console.WriteLine("MouseEnter")) 
     ..Items.Add(
      new Button() 
       ..Content = "abc"; 
       ..Click += ((s, e) => Console.WriteLine("button 1 Click"))) 
     ..Items.Add(
      new Button() 
       ..Content = "def"; 
       ..Click += (s, e) => (Console.WriteLine("button 2 Click")))); 

我的問題是,有沒有辦法來模擬或密切近似方法級聯在C#中?

這是我想出的一種方法。鑑於這種擴展方法:

public static T Call<T>(this T obj, Action<T> proc) 
{ 
    proc(obj); 

    return obj; 
} 

上面的例子可以按如下方式寫入:

ContentPanel.Children.Add(
    new ListBox().Call(o => { 
      o.Width = 200; 
      o.MouseEnter += (s, e) => Console.WriteLine("MouseEnter"); 
      o.Items.Add(
       new Button().Call(b => { 
         b.Content = "abc"; 
         b.Click += (s, e) => Console.WriteLine("button 1 Click"); })); 
      o.Items.Add(
       new Button().Call(b => { 
        b.Content = "def"; 
        b.Click += (s, e) => Console.WriteLine("button 2 Click"); })); })); 

我不認爲這是相當。 :-)但它本質上確保了應用流暢的風格。

+1

任何進一步的細節,你根本就沒有找[對象初始](http://msdn.microsoft.com/en-us/library/vstudio/bb384062.aspx)? –

+2

@SimonWhitehead對象初始值設定項僅適用於屬性。該示例包含事件和方法調用。 – juharr

+3

我認爲你所擁有的儘可能接近你所能得到的。我真的不認爲這比你的Dart例子更醜陋。 – juharr

回答

3

我認爲你可以通過使用流暢的界面達到你想達到的目標。它將允許您鏈接方法以一個語句創建和初始化對象。

你可以得到類似的東西:

Fluent fluent = new Fluent(); 
var panel = fluent.CreateControlPanel().Children() 
       .AddListBox().SetWidth(200).AddMouseEnterEvent((s, e) => { }).Create() 
       .AddTextBox().SetText("Foo").Create() 
       .GetControlPanel(); 

的想法是,一個方法返回一個對象,允許初始化另一個對象。初始化鏈可以在任何項目處調用「終結器」方法(大於Create),該方法返回原始對象(在Children之上)以繼續添加其他對象或配置初始對象。

因此,例如在AddListBox返回ListBoxSetup類型的對象,其具有一串像SetWidthAddMouseEnterEvent方法。在這種情況下,Children也將是一個特殊對象(如類型),它有一堆方法,如AddListBoxAddTextBox。每種方法都負責創建類型爲ListBoxTextBox的對象或要創建的基礎對象的設置屬性。 Fluent將有一個方法返回你的整個對象結構正確的設置。

看看這個鏈接: http://blog.raffaeu.com/archive/2010/06/26/how-to-write-fluent-interface-with-c-and-lambda.aspx

這裏的底層代碼的創建與上述落得一個例子。當然,代碼在架構上可以有很大的改進,但這僅僅是爲了這個例子。

public class Fluent 
{ 
    public ControlPanelCreator CreateControlPanel() 
    { 
     return new ControlPanelCreator(new StackPanel(), this); 
    } 
} 

public class ControlPanelCreator 
{ 
    #region Fields 
    private Fluent fluent; 
    private Panel panel; 
    #endregion 

    #region Constructors 
    internal ControlPanelCreator(Panel panel, Fluent fluent) 
    { 
     this.fluent = fluent; 
     this.panel = panel; 
    } 
    #endregion 

    #region Methods 
    public ControlPanelChildrenCreator Children() 
    { 
     return new ControlPanelChildrenCreator(this.panel, this); 
    } 
    #endregion 
} 

public class ControlPanelChildrenCreator 
{ 
    #region Fields 
    private ControlPanelCreator panelCreator; 
    private Panel panel; 
    #endregion 

    #region Constructors 
    internal ControlPanelChildrenCreator(Panel panel, ControlPanelCreator panelCreator) 
    { 
     this.panel = panel; 
     this.panelCreator = panelCreator; 
    } 
    #endregion 

    #region Methods 
    public ListBoxCreator AddListBox() 
    { 
     ListBox listBox = new ListBox(); 
     this.panel.Children.Add(listBox); 
     return new ListBoxCreator(listBox, this); 
    } 

    public TextBoxCreator AddTextBox() 
    { 
     TextBox textBox = new TextBox(); 
     this.panel.Children.Add(textBox); 
     return new TextBoxCreator(textBox, this); 
    } 

    public Panel GetControlPanel() 
    { 
     return this.panel; 
    } 
    #endregion 
} 

public class ListBoxCreator 
{ 
    #region Fields 
    private ListBox listbox; 
    private ControlPanelChildrenCreator parentCreator; 
    #endregion 

    #region Constructors 
    internal ListBoxCreator(ListBox listBox, ControlPanelChildrenCreator parentCreator) 
    { 
     this.listbox = listBox; 
     this.parentCreator = parentCreator; 
    } 
    #endregion 

    #region Methods 
    public ListBoxCreator SetWidth(int width) 
    { 
     this.listbox.Width = width; 
     return this; 
    } 

    public ListBoxCreator AddMouseEnterEvent(Action<object, MouseEventArgs> action) 
    { 
     this.listbox.MouseEnter += new MouseEventHandler(action); 
     return this; 
    } 

    public ControlPanelChildrenCreator Create() 
    { 
     return this.parentCreator; 
    } 
    #endregion 
} 

public class TextBoxCreator 
{ 
    #region Fields 
    private TextBox textBox; 
    private ControlPanelChildrenCreator parentCreator; 
    #endregion 

    #region Constructors 
    internal TextBoxCreator(TextBox textBox, ControlPanelChildrenCreator parentCreator) 
    { 
     this.textBox = textBox; 
     this.parentCreator = parentCreator; 
    } 
    #endregion 

    #region Methods 
    public TextBoxCreator SetText(string defaultText) 
    { 
     this.textBox.Text = defaultText; 
     return this; 
    } 

    public ControlPanelChildrenCreator Create() 
    { 
     return this.parentCreator; 
    } 
    #endregion 
} 
0

我支持以前的答案。我喜歡添加的東西很少,因爲我創建了類似的東西。

有兩件事,要麼是單班做事。意思是形式,有addcolor,addData等,可以是形式有按鈕而不是按鈕有顏色

現在在這種情況下你需要使用接口鏈接,意味着方法返回類型是接口,並且所有接口都是由該類實現的並且該方法僅返回「this」。

當你創建接口的對象的時候,這會做到這一點。然後鏈接它。在這裏舉例很難,但如果你仍然想要,我可以提供例子。

讓我知道,如果需要