2013-01-09 17 views
6

Ngôn ngữ lập trình Dart có hỗ trợ cho method cascades. Phương pháp thác sẽ cho phép Silverlight/WPF C# mã sau:Ghép phương pháp mô phỏng trong 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); 

được viết thay vì như:

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âu hỏi của tôi là, liệu có một cách để mô phỏng hoặc thác phương pháp xấp xỉ chặt chẽ trong C#?

Đây là một cách tiếp cận mà tôi đã đưa ra. Với phương pháp này mở rộng:

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

    return obj; 
} 

ví dụ trên có thể được viết như sau:

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"); })); })); 

tôi sẽ không cho rằng đó là khá. :-) Nhưng về cơ bản nó cho phép một phong cách thông thạo được áp dụng.

+1

Bạn chỉ đơn giản là không tìm kiếm [Object initializers] (http://msdn.microsoft.com/en-us/library/vstudio/bb384062.aspx)? –

+2

@SimonWhitehead Trình khởi tạo đối tượng chỉ hoạt động với các thuộc tính. Ví dụ này bao gồm các sự kiện và các cuộc gọi phương thức. – juharr

+3

Tôi nghĩ rằng những gì bạn có là gần như bạn có thể nhận được. Và tôi thành thật không nghĩ rằng nó xấu hơn nhiều so với ví dụ Dart của bạn. – juharr

Trả lời

3

Tôi nghĩ bạn có thể tiếp cận gần với những gì bạn muốn đạt được bằng cách sử dụng giao diện thông thạo. Nó sẽ cho phép bạn chuỗi các phương thức để tạo và khởi tạo các đối tượng trong một câu lệnh.

Bạn có thể nhận được một cái gì đó như thế:

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

Ý tưởng là một phương thức trả về một đối tượng cho phép để khởi tạo một đối tượng khác. Một chuỗi khởi tạo có thể gọi bất kỳ mục nào là phương thức "finalizer" (trên Create) trả về đối tượng gốc (trên Children) để tiếp tục thêm các đối tượng khác hoặc định cấu hình một đối tượng ban đầu.

Ví dụ: AddListBox trả về một đối tượng thuộc loại ListBoxSetup có một loạt các phương thức như SetWidth hoặc AddMouseEnterEvent. Trong trường hợp này, Children cũng sẽ là một đối tượng đặc biệt (như loại) có một loạt các phương thức như AddListBox hoặc AddTextBox. Mỗi phương thức đều có trách nhiệm tạo đối tượng thuộc loại ListBox hoặc TextBox hoặc thuộc tính thiết lập của đối tượng bên dưới được tạo. Fluent sẽ có phương thức trả về toàn bộ cấu trúc đối tượng của bạn thiết lập chính xác.

Hãy xem liên kết này: http://blog.raffaeu.com/archive/2010/06/26/how-to-write-fluent-interface-with-c-and-lambda.aspx

Dưới đây là một ví dụ về các mã cơ bản tạo ra để kết thúc với trên. Tất nhiên mã có thể được cải thiện rất nhiều trong kiến ​​trúc của nó nhưng nó ở đây chỉ vì lợi ích của ví dụ.

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

Tôi đã hỗ trợ câu trả lời trước. Rất ít điều tôi muốn thêm, vì tôi đã tạo ra những thứ tương tự.

Có hai điều, hoặc bạn đang có lớp đơn làm việc. Có nghĩa là hình thức, có addcolor, addData vv và có thể được hình thức có nút và hơn nút có màu

Bây giờ trong trường hợp này bạn cần phải sử dụng giao diện, nghĩa là phương thức trả về sẽ là giao diện, và tất cả các giao diện được thực hiện bởi lớp đó và các phương thức đó chỉ trả lại "này".

Điều này sẽ thực hiện thủ thuật, trong khi bạn tạo đối tượng giao diện.Và sau đó chuỗi nó qua. Sẽ rất khó để đưa ra ví dụ ở đây, nhưng nếu bạn vẫn muốn tôi có thể cung cấp ví dụ.

Hãy cho tôi biết nếu có thêm thông tin chi tiết cần thiết