Modeling the cascade method in C #

The Dart programming language supports the cascade method . Cascading methods will allow you to use the following Silverlight / WPF C # code:

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

instead, write:

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

My question is, is there a way to simulate or closely approximate cascades of methods in C #?

Here is one approach I came up with. Given this extension method:

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

the above example can be written as follows:

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

I would not argue that it is beautiful. :-) But it really allows you to apply a free style.

+6
source share
2 answers

I think you can get closer to what you want to achieve using the free interface. This allows you to chain methods to create and initialize objects in a single expression.

You can get something like this:

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

The idea is that the method returns an object that allows you to initialize another object. The initializer chain can call the finalizer method (above Create ) on any element, which returns the original object (above Children ) to continue adding other objects or customizing the source.

So, for example, an object of type AddListBox returned to ListBoxSetup , which has a bunch of methods like SetWidth or AddMouseEnterEvent . In this case, Children will also be a special object (like ChildSetup , for example) that has a bunch of methods like AddListBox or AddTextBox . Each of these methods is responsible for creating an object of type ListBox or TextBox or setting properties of the base object that will be created. Fluent will have a method that correctly sets your object structure.

Take a look at this link: http://blog.raffaeu.com/archive/2010/06/26/how-to-write-fluent-interface-with-c-and-lambda.aspx

Here is an example of the base code created as described above. Of course, the code can be significantly improved in its architecture, but it is only for example.

 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 } 
+3
source

I supported the previous answer. Not only do I like to add as I created similar things.

There are two things: you have one class that does something. Form tool, has addcolor, addData, etc. And it can be shaped, has a button, and the button has a color

Now in this case you need to connect using the interface, which means that the return type method will be the interface, and the entire interface is implemented by this class, and the methods return only "this".

This will do the trick while you create the interface object. And then strain it. It will be difficult to give an example here, but if you still want to, I can give an example.

Let me know if any additional data is required.

0
source

All Articles