tag:blogger.com,1999:blog-66645990313839099152024-02-20T12:55:43.909+00:00GSharperGSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.comBlogger19125tag:blogger.com,1999:blog-6664599031383909915.post-60267626257518959452008-09-01T06:35:00.005+00:002008-09-01T07:20:51.887+00:00Builder patternI was writing unit tests when I stumbled on a problem. I had a class TransitionInfo which I couldn't instantiate.<br /><br />The constructor was made internal. Also, all the properties were getters, so I couldn't set any of them. So, there was only one thing todo: Reflection !!<br /><br />The TransitionInfo object was used in more than 1 unit tests. In fact, it was used in alot of them. So I had to copy all this ugly reflection code in each unit test.<br /><br />I couldn't do this of course. I hate copy pasting.<br /><br />So I talked to our Architect on the team and he put me on the right track.<br /><br />This is how I implemented the solution:<br /><br />First I had to create a sort of builder class which was goin to encapsulate all of the reflection code. The purpose of the builder class was to give me a constructed TransitionInfo object.<br /><br />This is the code:<br /><br />internal class TransitionInfoBuilder<br />{<br />// Create our return object<br />private TransitionInfo expectedTransitionInfo;<br /><br />public TransitionInfoBuilder()<br />{<br />Type type = typeof(TransitionInfo);<br />Type[] constructorParameterTypes = new Type[]<br />{ typeof(TransitionTrigger), typeof(string), typeof(int), typeof(string), typeof(string),<br />typeof(string) };<br /><br />// Get the internal constructor<br />ConstructorInfo cInfo = type.GetConstructor(BindingFlags.Instance<br />BindingFlags.NonPublic, null,<br />CallingConventions.HasThis,<br />constructorParameterTypes,<br />null);<br /><br />// Call invoke and instantiate the return object<br />expectedTransitionInfo = (TransitionInfo) cInfo.Invoke(new object[]<br />{ TransitionTrigger.After, "", 0, "", "", "" }); }<br /><br /><br />// Let's fill in some private field:<br />public TransitionInfoBuilder WithItemId(int itemId)<br />{<br />// Set the private field<br />SetTransitionField(itemId, "m_ItemId");<br /><br />// Return a builder object<br />return this;<br />}<br /><br />// Now we have to expose the transitionInfo object<br />public TransitionInfo Stub<br />{<br /> get<br /> {<br /> return this.expectedTransitionInfo;<br /> }<br />}<br /><br />// Use reflection to set the private field<br /><br />private void SetTransitionField(object fieldValue, string fieldName)<br />{<br /> Type myType = typeof(TransitionInfo);<br /> FieldInfo myFieldInfo = myType.GetField(fieldName, BindingFlags.NonPublic<br /> BindingFlags.Instance);<br /><br /> myFieldInfo.SetValue(expectedTransitionInfo, fieldValue);<br />}<br /><br />Now we can call the builder class and retrieve our stubbed TransitionInfo object<br /><br />TransitionInfo transitionInfo = new TransitionInfoBuilder()<br />.WithItemId(1)<br />.Stub;<br /><br />Greetz,<br />Glenn<br /><br />comments are always welcomeGSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.com194tag:blogger.com,1999:blog-6664599031383909915.post-26512863096494571062007-08-17T10:40:00.000+00:002007-08-17T10:43:03.268+00:00Searching your entire solution suddenly doesn't work anymoreI just got this error when trying to search my entire solution<br /><br />"Find was stopped in progress"<br /><br />You never guess what the solution is:<br /><br />Just press "Ctrl + Scroll Lock"<br /><br />And it works again. What the ............<br /><br />Greetz,<br />GlennGSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.com1tag:blogger.com,1999:blog-6664599031383909915.post-19692437010808754272007-08-13T17:17:00.001+00:002007-08-13T17:17:37.754+00:00Sorting databound datagridviews<p>I was asked to provide sorting on a databound gridview. At first it looked easy. Just bind my generic list to the gridview and enable sorting. </p> <p>But, no can do. You cannot bind a standard generic list to a datagridview.</p> <p>The solution is to create your own sortable binding list. This is the way to do it</p> <p>First we create our own implementation of the list</p> <p> <div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:b0f9b92d-3ea7-4d8e-b221-9e8bc9ea223b" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; width: 461px; padding-top: 0px"><pre style="width:100%;background-color:#DDDDDD;font-size:80%"><div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">class</span><span style="color: #000000;"> SortableBindingList</span><span style="color: #000000;"><</span><span style="color: #000000;">T</span><span style="color: #000000;">></span><span style="color: #000000;"> : BindingList</span><span style="color: #000000;"><</span><span style="color: #000000;">T</span><span style="color: #000000;">></span><span style="color: #000000;"><br />{<br /> </span><span style="color: #0000FF;">private</span><span style="color: #000000;"> </span><span style="color: #0000FF;">bool</span><span style="color: #000000;"> _isSorted;<br /><br /> </span><span style="color: #0000FF;">protected</span><span style="color: #000000;"> </span><span style="color: #0000FF;">override</span><span style="color: #000000;"> </span><span style="color: #0000FF;">bool</span><span style="color: #000000;"> SupportsSortingCore<br /> {<br /> </span><span style="color: #0000FF;">get</span><span style="color: #000000;"><br /> {<br /> </span><span style="color: #0000FF;">return</span><span style="color: #000000;"> </span><span style="color: #0000FF;">true</span><span style="color: #000000;">;<br /> }<br /> }<br /><br /> </span><span style="color: #0000FF;">protected</span><span style="color: #000000;"> </span><span style="color: #0000FF;">override</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> ApplySortCore(<br /> PropertyDescriptor property, ListSortDirection <br /> direction)<br /> {<br /> List</span><span style="color: #000000;"><</span><span style="color: #000000;">T</span><span style="color: #000000;">></span><span style="color: #000000;"> items </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">this</span><span style="color: #000000;">.Items </span><span style="color: #0000FF;">as</span><span style="color: #000000;"> List</span><span style="color: #000000;"><</span><span style="color: #000000;">T</span><span style="color: #000000;">></span><span style="color: #000000;">;<br /> </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (items </span><span style="color: #000000;">!=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">null</span><span style="color: #000000;">)<br /> {<br /> PropertyComparer</span><span style="color: #000000;"><</span><span style="color: #000000;">T</span><span style="color: #000000;">></span><span style="color: #000000;"> pc </span><span style="color: #000000;">=</span><span style="color: #000000;"> <br /> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> PropertyComparer</span><span style="color: #000000;"><</span><span style="color: #000000;">T</span><span style="color: #000000;">></span><span style="color: #000000;">(property, <br /> direction);<br /> <br /> items.Sort(pc);<br /> _isSorted </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">true</span><span style="color: #000000;">;<br /> }<br /> </span><span style="color: #0000FF;">else</span><span style="color: #000000;"><br /> {<br /> _isSorted </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">false</span><span style="color: #000000;">;<br /> }<br /><br /> </span><span style="color: #0000FF;">this</span><span style="color: #000000;">.OnListChanged(<br /> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> ListChangedEventArgs(ListChangedType.Reset, <br /> </span><span style="color: #000000;">-</span><span style="color: #800080;">1</span><span style="color: #000000;">));<br /> }<br /><br /> </span><span style="color: #0000FF;">protected</span><span style="color: #000000;"> </span><span style="color: #0000FF;">override</span><span style="color: #000000;"> </span><span style="color: #0000FF;">bool</span><span style="color: #000000;"> IsSortedCore<br /> {<br /> </span><span style="color: #0000FF;">get</span><span style="color: #000000;"> { </span><span style="color: #0000FF;">return</span><span style="color: #000000;"> _isSorted; }<br /> }<br />}</span></div></pre></div></p><br /><p>Now it's time to implement our own sorting algorithm using reflection</p><br /><p><br /><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:6e4253f0-3603-473d-a41d-00c0a9ea5eb3" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; width: 453px; padding-top: 0px"><pre style="width:100%;background-color:#DDDDDD;font-size:80%"><div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">class</span><span style="color: #000000;"> PropertyComparer</span><span style="color: #000000;"><</span><span style="color: #000000;">T</span><span style="color: #000000;">></span><span style="color: #000000;"> : System.Collections.Generic.IComparer</span><span style="color: #000000;"><</span><span style="color: #000000;">T</span><span style="color: #000000;">></span><span style="color: #000000;"><br />{<br /> </span><span style="color: #0000FF;">private</span><span style="color: #000000;"> PropertyDescriptor _property;<br /> </span><span style="color: #0000FF;">private</span><span style="color: #000000;"> ListSortDirection _direction;<br /><br /> </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> PropertyComparer(PropertyDescriptor property,<br /> ListSortDirection direction)<br /> {<br /> _property </span><span style="color: #000000;">=</span><span style="color: #000000;"> property;<br /> _direction </span><span style="color: #000000;">=</span><span style="color: #000000;"> direction;<br /> }<br /><br /> </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">int</span><span style="color: #000000;"> Compare(T col1, T col2)<br /> {<br /> </span><span style="color: #0000FF;">object</span><span style="color: #000000;"> col1Value </span><span style="color: #000000;">=</span><span style="color: #000000;"> GetPropertyValue(col1, <br /> _property.Name);<br /><br /> </span><span style="color: #0000FF;">object</span><span style="color: #000000;"> col2Value </span><span style="color: #000000;">=</span><span style="color: #000000;"> GetPropertyValue(col2, <br /> _property.Name);<br /><br /> </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (_direction </span><span style="color: #000000;">==</span><span style="color: #000000;"> ListSortDirection.Ascending)<br /> {<br /> </span><span style="color: #0000FF;">return</span><span style="color: #000000;"> CompareAscending(col1Value, <br /> col2Value);<br /> }<br /> </span><span style="color: #0000FF;">else</span><span style="color: #000000;"><br /> {<br /> </span><span style="color: #0000FF;">return</span><span style="color: #000000;"> CompareDescending(col1Value, <br /> col2Value);<br /> }<br /> }<br /><br /> </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">bool</span><span style="color: #000000;"> Equals(T col1, T col2)<br /> {<br /> </span><span style="color: #0000FF;">return</span><span style="color: #000000;"> col1.Equals(col2);<br /> }<br /><br /> </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">int</span><span style="color: #000000;"> GetHashCode(T obj)<br /> {<br /> </span><span style="color: #0000FF;">return</span><span style="color: #000000;"> obj.GetHashCode();<br /> }<br /><br /> </span><span style="color: #0000FF;">private</span><span style="color: #000000;"> </span><span style="color: #0000FF;">int</span><span style="color: #000000;"> CompareAscending(</span><span style="color: #0000FF;">object</span><span style="color: #000000;"> x, </span><span style="color: #0000FF;">object</span><span style="color: #000000;"> y)<br /> {<br /> </span><span style="color: #0000FF;">int</span><span style="color: #000000;"> result;<br /><br /> </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (x </span><span style="color: #0000FF;">is</span><span style="color: #000000;"> IComparable)<br /> {<br /> result </span><span style="color: #000000;">=</span><span style="color: #000000;"> ((IComparable)x).CompareTo(y);<br /> }<br /> </span><span style="color: #0000FF;">else</span><span style="color: #000000;"> </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (x.Equals(y))<br /> {<br /> result </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">0</span><span style="color: #000000;">;<br /> }<br /> </span><span style="color: #0000FF;">else</span><span style="color: #000000;"> result </span><span style="color: #000000;">=</span><span style="color: #000000;"> ((IComparable)x).CompareTo(y);<br /><br /> </span><span style="color: #0000FF;">return</span><span style="color: #000000;"> result;<br /> }<br /><br /> </span><span style="color: #0000FF;">private</span><span style="color: #000000;"> </span><span style="color: #0000FF;">int</span><span style="color: #000000;"> CompareDescending(</span><span style="color: #0000FF;">object</span><span style="color: #000000;"> x, </span><span style="color: #0000FF;">object</span><span style="color: #000000;"> y)<br /> {<br /> </span><span style="color: #0000FF;">return</span><span style="color: #000000;"> </span><span style="color: #000000;">-</span><span style="color: #000000;">CompareAscending(x, y);<br /> }<br /><br /> </span><span style="color: #0000FF;">private</span><span style="color: #000000;"> </span><span style="color: #0000FF;">object</span><span style="color: #000000;"> GetPropertyValue(T value, </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> <br /> property)<br /> {<br /> PropertyInfo propertyInfo </span><span style="color: #000000;">=</span><span style="color: #000000;"> <br /> value.GetType().GetProperty(property);<br /> <br /> </span><span style="color: #0000FF;">return</span><span style="color: #000000;"> propertyInfo.GetValue(value, </span><span style="color: #0000FF;">null</span><span style="color: #000000;">);<br /> }<br />}<br /></span></div></pre></div>Now it's time to fill and bind the custom made list. lI've created this simple Person class for demonstration purposes.</p><br /><p><br /><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:3e346a5b-7cc3-4d6d-b7d7-7274ca5e963f" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; width: 452px; padding-top: 0px"><pre style="width:100%;background-color:#DDDDDD;font-size:80%"><div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000;">dataGridView1.AutoGenerateColumns </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">false</span><span style="color: #000000;">;<br /><br />Person pers1 </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Person();<br />Person pers2 </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Person();<br />Person pers3 </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Person();<br />Person pers4 </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Person();<br /><br />pers1.FirstName </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">Glenn</span><span style="color: #800000;">"</span><span style="color: #000000;">;<br />pers2.FirstName </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">San</span><span style="color: #800000;">"</span><span style="color: #000000;">;<br />pers3.FirstName </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">Yannick</span><span style="color: #800000;">"</span><span style="color: #000000;">;<br />pers4.FirstName </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">Alfred</span><span style="color: #800000;">"</span><span style="color: #000000;">;<br /><br />pers1.LastName </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">Goovaerts</span><span style="color: #800000;">"</span><span style="color: #000000;">;<br />pers2.LastName </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">Zodiac</span><span style="color: #800000;">"</span><span style="color: #000000;">;<br />pers3.LastName </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">Smits</span><span style="color: #800000;">"</span><span style="color: #000000;">;<br />pers4.LastName </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">"</span><span style="color: #800000;">Anvers</span><span style="color: #800000;">"</span><span style="color: #000000;">;<br /><br />pers1.Age </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">6</span><span style="color: #000000;">;<br />pers2.Age </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">18</span><span style="color: #000000;">;<br />pers3.Age </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">78</span><span style="color: #000000;">;<br />pers4.Age </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800080;">1</span><span style="color: #000000;">;<br /><br />pers1.BirthDate </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> DateTime(</span><span style="color: #800080;">2007</span><span style="color: #000000;">,</span><span style="color: #800080;">1</span><span style="color: #000000;">,</span><span style="color: #800080;">1</span><span style="color: #000000;">,</span><span style="color: #800080;">12</span><span style="color: #000000;">,</span><span style="color: #800080;">5</span><span style="color: #000000;">,</span><span style="color: #800080;">4</span><span style="color: #000000;">);<br />pers2.BirthDate </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> DateTime(</span><span style="color: #800080;">2007</span><span style="color: #000000;">,</span><span style="color: #800080;">1</span><span style="color: #000000;">, </span><span style="color: #800080;">1</span><span style="color: #000000;">, </span><span style="color: #800080;">12</span><span style="color: #000000;">, </span><span style="color: #800080;">5</span><span style="color: #000000;">, </span><span style="color: #800080;">3</span><span style="color: #000000;">);<br />pers3.BirthDate </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> DateTime(</span><span style="color: #800080;">2007</span><span style="color: #000000;">, </span><span style="color: #800080;">1</span><span style="color: #000000;">, </span><span style="color: #800080;">1</span><span style="color: #000000;">, </span><span style="color: #800080;">12</span><span style="color: #000000;">, </span><span style="color: #800080;">5</span><span style="color: #000000;">, </span><span style="color: #800080;">5</span><span style="color: #000000;">);<br />pers4.BirthDate </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> DateTime(</span><span style="color: #800080;">2005</span><span style="color: #000000;">, </span><span style="color: #800080;">1</span><span style="color: #000000;">, </span><span style="color: #800080;">1</span><span style="color: #000000;">, </span><span style="color: #800080;">12</span><span style="color: #000000;">, </span><span style="color: #800080;">5</span><span style="color: #000000;">, </span><span style="color: #800080;">4</span><span style="color: #000000;">);<br /><br />SortableBindingList</span><span style="color: #000000;"><</span><span style="color: #000000;">Person</span><span style="color: #000000;">></span><span style="color: #000000;"> source </span><span style="color: #000000;">=</span><span style="color: #000000;"> <br /></span><span style="color: #0000FF;">new</span><span style="color: #000000;"> SortableBindingList</span><span style="color: #000000;"><</span><span style="color: #000000;">Person</span><span style="color: #000000;">></span><span style="color: #000000;">();<br /> <br />source.Add(pers1);<br />source.Add(pers2);<br />source.Add(pers3);<br />source.Add(pers4);<br /><br /></span><span style="color: #0000FF;">this</span><span style="color: #000000;">.dataGridView1.DataSource </span><span style="color: #000000;">=</span><span style="color: #000000;"> source;<br />dataGridView1.AutoResizeColumns();</span></div></pre></div>The only thing we have to do now is to react to the column header click</p><br /><p><br /><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:c2e1c65a-444c-475a-b19e-2c6c1e3f654f" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; width: 448px; padding-top: 0px"><pre style="width:100%;background-color:#DDDDDD;font-size:80%"><div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF;">private</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> dataGridView1_ColumnHeaderMouseClick<br />(</span><span style="color: #0000FF;">object</span><span style="color: #000000;"> sender, DataGridViewCellMouseEventArgs e)<br />{<br /> DataGridViewColumn selectedColumn </span><span style="color: #000000;">=</span><span style="color: #000000;"> <br /> dataGridView1.Columns[e.ColumnIndex];<br /> <br /> ListSortDirection direction;<br /><br /> </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (sortedDescending </span><span style="color: #000000;">==</span><span style="color: #000000;"> </span><span style="color: #0000FF;">false</span><span style="color: #000000;">)<br /> {<br /> direction </span><span style="color: #000000;">=</span><span style="color: #000000;"> ListSortDirection.Descending;<br /> sortedDescending </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">true</span><span style="color: #000000;">;<br /> }<br /> </span><span style="color: #0000FF;">else</span><span style="color: #000000;"><br /> {<br /> direction </span><span style="color: #000000;">=</span><span style="color: #000000;"> ListSortDirection.Ascending;<br /> sortedDescending </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">false</span><span style="color: #000000;">;<br /> }<br /><br /> dataGridView1.Sort(selectedColumn, direction);<br /><br /> selectedColumn.HeaderCell.SortGlyphDirection </span><span style="color: #000000;">=</span><span style="color: #000000;"><br /> direction </span><span style="color: #000000;">==</span><span style="color: #000000;"> ListSortDirection.Ascending </span><span style="color: #000000;">?</span><span style="color: #000000;"><br /> SortOrder.Ascending : SortOrder.Descending;<br />}</span></div></pre></div>Hope this can help someone. Greetz, G</p>GSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.com5tag:blogger.com,1999:blog-6664599031383909915.post-56218042026939408302007-06-12T08:51:00.001+00:002007-06-12T08:51:43.461+00:00Deserialize XML file to an Domain object<p>Some time ago, I read this article on how to deserialize XML files into objects and I thought, let's give this a try. Let's try a simple domain class Person which has a couple of properties like FirstName, LastName and an Address List for which I created another domain class.</p> <p>I started with the XML file</p> <p> <div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:5948591f-c408-4d0a-8c8e-1b528ff861ed" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; width: 449px; padding-top: 0px"><pre style="width:100%;background-color:#EEEEEE;font-size:80%"><div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000;"><?</span><span style="color: #000000;">xml version</span><span style="color: #000000;">=</span><span style="color: #800000;">"</span><span style="color: #800000;">1.0</span><span style="color: #800000;">"</span><span style="color: #000000;"> encoding</span><span style="color: #000000;">=</span><span style="color: #800000;">"</span><span style="color: #800000;">utf-8</span><span style="color: #800000;">"</span><span style="color: #000000;"> </span><span style="color: #000000;">?></span><span style="color: #000000;"><br /></span><span style="color: #000000;"><</span><span style="color: #000000;">Persons xmlns</span><span style="color: #000000;">=</span><span style="color: #800000;">"</span><span style="color: #800000;">http://personreader</span><span style="color: #800000;">"</span><span style="color: #000000;"> DefaultProfile</span><span style="color: #000000;">=</span><span style="color: #800000;">"</span><span style="color: #800000;">XmlToObjectDeserialization</span><span style="color: #800000;">"</span><span style="color: #000000;">></span><span style="color: #000000;"><br /> </span><span style="color: #000000;"><</span><span style="color: #000000;">PersonInfo AssemblyFile</span><span style="color: #000000;">=</span><span style="color: #800000;">"</span><span style="color: #800000;">Domain.dll</span><span style="color: #800000;">"</span><span style="color: #000000;"> </span><span style="color: #000000;">></span><span style="color: #000000;"><br /> </span><span style="color: #000000;"><</span><span style="color: #000000;">FirstName</span><span style="color: #000000;">></span><span style="color: #000000;">John</span><span style="color: #000000;"></</span><span style="color: #000000;">FirstName</span><span style="color: #000000;">></span><span style="color: #000000;"><br /> </span><span style="color: #000000;"><</span><span style="color: #000000;">LastName</span><span style="color: #000000;">></span><span style="color: #000000;">Doe</span><span style="color: #000000;"></</span><span style="color: #000000;">LastName</span><span style="color: #000000;">></span><span style="color: #000000;"><br /> </span><span style="color: #000000;"><</span><span style="color: #000000;">Address</span><span style="color: #000000;">></span><span style="color: #000000;"><br /> </span><span style="color: #000000;"><</span><span style="color: #000000;">StreetName</span><span style="color: #000000;">></span><span style="color: #000000;">Hit the road street</span><span style="color: #000000;"></</span><span style="color: #000000;">StreetName</span><span style="color: #000000;">></span><span style="color: #000000;"><br /> </span><span style="color: #000000;"><</span><span style="color: #000000;">HouseNumber</span><span style="color: #000000;">></span><span style="color: #800080;">6</span><span style="color: #000000;"></</span><span style="color: #000000;">HouseNumber</span><span style="color: #000000;">></span><span style="color: #000000;"><br /> </span><span style="color: #000000;"><</span><span style="color: #000000;">PostalCode</span><span style="color: #000000;">></span><span style="color: #000000;">5800B</span><span style="color: #000000;"></</span><span style="color: #000000;">PostalCode</span><span style="color: #000000;">></span><span style="color: #000000;"><br /> </span><span style="color: #000000;"><</span><span style="color: #000000;">Location</span><span style="color: #000000;">></span><span style="color: #000000;">New York</span><span style="color: #000000;"></</span><span style="color: #000000;">Location</span><span style="color: #000000;">></span><span style="color: #000000;"><br /> </span><span style="color: #000000;"></</span><span style="color: #000000;">Address</span><span style="color: #000000;">></span><span style="color: #000000;"><br /> </span><span style="color: #000000;"><</span><span style="color: #000000;">Address</span><span style="color: #000000;">></span><span style="color: #000000;"><br /> </span><span style="color: #000000;"><</span><span style="color: #000000;">StreetName</span><span style="color: #000000;">></span><span style="color: #000000;">Secondary Address Street</span><span style="color: #000000;"></</span><span style="color: #000000;">StreetName</span><span style="color: #000000;">></span><span style="color: #000000;"><br /> </span><span style="color: #000000;"><</span><span style="color: #000000;">HouseNumber</span><span style="color: #000000;">></span><span style="color: #800080;">44</span><span style="color: #000000;"></</span><span style="color: #000000;">HouseNumber</span><span style="color: #000000;">></span><span style="color: #000000;"><br /> </span><span style="color: #000000;"><</span><span style="color: #000000;">PostalCode</span><span style="color: #000000;">></span><span style="color: #800080;">1500</span><span style="color: #000000;"></</span><span style="color: #000000;">PostalCode</span><span style="color: #000000;">></span><span style="color: #000000;"><br /> </span><span style="color: #000000;"><</span><span style="color: #000000;">Location</span><span style="color: #000000;">></span><span style="color: #000000;">California</span><span style="color: #000000;"></</span><span style="color: #000000;">Location</span><span style="color: #000000;">></span><span style="color: #000000;"><br /> </span><span style="color: #000000;"></</span><span style="color: #000000;">Address</span><span style="color: #000000;">></span><span style="color: #000000;"><br /> </span><span style="color: #000000;"></</span><span style="color: #000000;">PersonInfo</span><span style="color: #000000;">></span><span style="color: #000000;"><br /></span><span style="color: #000000;"></</span><span style="color: #000000;">Persons</span><span style="color: #000000;">></span></div></pre></div></p><br /><p>The next thing to do, is create the domain classes. These classes have to reflect the XML file's properties. We start with the Person class:</p><br /><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:42e42672-3baf-4c78-b317-1ace4e8dbbc5" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; width: 451px; padding-top: 0px"><pre style="width:100%;background-color:#EEEEEE;font-size:80%"><div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF;">namespace</span><span style="color: #000000;"> Domain<br />{<br /> [XmlRoot(</span><span style="color: #800000;">"</span><span style="color: #800000;">Persons</span><span style="color: #800000;">"</span><span style="color: #000000;">,Namespace</span><span style="color: #000000;">=</span><span style="color: #800000;">"</span><span style="color: #800000;">http://personreader</span><span style="color: #800000;">"</span><span style="color: #000000;">)]<br /> </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">class</span><span style="color: #000000;"> Persons<br /> {<br /> </span><span style="color: #008000;">//</span><span style="color: #008000;"> Return array of PersonInfo objects</span><span style="color: #008000;"><br /></span><span style="color: #000000;"> [XmlElement(</span><span style="color: #800000;">"</span><span style="color: #800000;">PersonInfo</span><span style="color: #800000;">"</span><span style="color: #000000;">)]<br /> </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> PersonInfo[] PersonInfos;<br /> }<br />}</span></div></pre></div><br /><p>Notice the Namespace property in the attribute. It has to be the same as the xmlns attribute in the XML file. We define a Person class with a list of PersonInfo objects. This PersonInfo class looks like this:</p><br /><p><br /><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:f20c845f-b5cf-4b0b-b106-14f692db8515" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="width:100%;background-color:#EEEEEE;font-size:80%"><div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF;">namespace</span><span style="color: #000000;"> Domain<br />{<br /> </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">class</span><span style="color: #000000;"> PersonInfo<br /> {<br /> </span><span style="color: #008000;">//</span><span style="color: #008000;"> Match properties of XML file</span><span style="color: #008000;"><br /></span><span style="color: #000000;"> [XmlAttribute]<br /> </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> AssemblyFile;<br /><br /> [XmlElement(</span><span style="color: #800000;">"</span><span style="color: #800000;">FirstName</span><span style="color: #800000;">"</span><span style="color: #000000;">)]<br /> </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> FirstName;<br /><br /> [XmlElement(</span><span style="color: #800000;">"</span><span style="color: #800000;">LastName</span><span style="color: #800000;">"</span><span style="color: #000000;">)]<br /> </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> LastName;<br /><br /> [XmlElement(</span><span style="color: #800000;">"</span><span style="color: #800000;">Address</span><span style="color: #800000;">"</span><span style="color: #000000;">)]<br /> </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> Address[] Address;<br /> }<br />}</span></div></pre></div></p><br /><p>The AssemblyFile string is marked as an XmlAttribute. All the others are XmlElements which corresponds with the XML file.</p><br /><p>Finally, the Address class:</p><br /><p><br /><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:c468d8d9-a3a2-4bc7-ab3e-fcec42b9283f" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; width: 445px; padding-top: 0px"><pre style="width:100%;background-color:#EEEEEE;font-size:80%"><div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF;">namespace</span><span style="color: #000000;"> Domain<br />{<br /> </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">class</span><span style="color: #000000;"> Address<br /> {<br /> [XmlElement(</span><span style="color: #800000;">"</span><span style="color: #800000;">StreetName</span><span style="color: #800000;">"</span><span style="color: #000000;">)]<br /> </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> StreetName;<br /><br /> [XmlElement(</span><span style="color: #800000;">"</span><span style="color: #800000;">HouseNumber</span><span style="color: #800000;">"</span><span style="color: #000000;">)]<br /> </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> HouseNumber;<br /><br /> [XmlElement(</span><span style="color: #800000;">"</span><span style="color: #800000;">PostalCode</span><span style="color: #800000;">"</span><span style="color: #000000;">)]<br /> </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> PostalCode;<br /><br /> [XmlElement(</span><span style="color: #800000;">"</span><span style="color: #800000;">Location</span><span style="color: #800000;">"</span><span style="color: #000000;">)]<br /> </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> Location;<br /> }<br />}</span></div></pre></div>Clearly no rocket science here.</p><br /><p>The only thing that has to be done is the deserialization of course. It works like this:</p><br /><p><br /><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:d824f0ca-e71f-4f13-a9e4-3feaf72bedb0" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"><pre style="width:100%;background-color:#EEEEEE;font-size:80%"><div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF;">private</span><span style="color: #000000;"> </span><span style="color: #0000FF;">static</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> DeserializeXml()<br />{<br /> </span><span style="color: #0000FF;">using</span><span style="color: #000000;"> (TextReader tr </span><span style="color: #000000;">=</span><span style="color: #000000;"> <br /> File.OpenText(</span><span style="color: #800000;">@"</span><span style="color: #800000;">PersonsData.xml</span><span style="color: #800000;">"</span><span style="color: #000000;">))<br /> {<br /> XmlSerializer serializer </span><span style="color: #000000;">=</span><span style="color: #000000;"> <br /> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> XmlSerializer(</span><span style="color: #0000FF;">typeof</span><span style="color: #000000;">(Persons));<br /> <br /> Persons persons </span><span style="color: #000000;">=</span><span style="color: #000000;"> <br /> (Persons)serializer.Deserialize(tr);<br /> }<br />}</span></div></pre></div></p><br /><p>Not that difficult. We open our file and put the content into a stream. Then we create a XmlSerializer and let it know that we want to deserialize to the Persons domain class.</p><br /><p>Finally deserialize the stream and we're done.</p><br /><p>Greetz, G </p>GSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.com1tag:blogger.com,1999:blog-6664599031383909915.post-23457291971914873172007-04-25T11:17:00.001+00:002007-04-25T11:17:45.503+00:00Convert integer array to string array<p>Today I needed to write some code to convert an integer array to a string array. Somebody told me to iterate over the integer array and fill the string array.</p> <p>I said to myself NO WAY. .NET has to have some build-in functionality to do this stuff. And it does. <a href="http://msdn2.microsoft.com/en-us/library/exc45z53.aspx">Array.Convert Generic Method</a> is the name. </p> <p>This is the code:</p> <p> <div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:1819b93d-e155-490e-b3f9-53994b848ec1" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; width: 440px; padding-top: 0px"><pre style="width:100%;background-color:#EEEEEE;font-size:80%"><div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF;">private</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> TestMethod(</span><span style="color: #0000FF;">int</span><span style="color: #000000;">[] intArray)<br />{ <br /> </span><span style="color: #0000FF;">string</span><span style="color: #000000;">[] stringArray </span><span style="color: #000000;">=</span><span style="color: #000000;"> <br /> Array.ConvertAll</span><span style="color: #000000;"><</span><span style="color: #0000FF;">int</span><span style="color: #000000;">,</span><span style="color: #0000FF;">string</span><span style="color: #000000;">></span><span style="color: #000000;"><br /> (intArray,</span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Converter</span><span style="color: #000000;"><</span><span style="color: #0000FF;">int</span><span style="color: #000000;">,</span><span style="color: #0000FF;">string</span><span style="color: #000000;">></span><span style="color: #000000;"> <br /> (ConvertIntToString));<br /><br /> </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> result </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">string</span><span style="color: #000000;">.Join(</span><span style="color: #800000;">"</span><span style="color: #800000;">,</span><span style="color: #800000;">"</span><span style="color: #000000;">, stringArray);<br />}<br /><br /></span><span style="color: #0000FF;">private</span><span style="color: #000000;"> </span><span style="color: #0000FF;">string</span><span style="color: #000000;"> ConvertIntToString(</span><span style="color: #0000FF;">int</span><span style="color: #000000;"> intParameter)<br />{<br /> </span><span style="color: #0000FF;">return</span><span style="color: #000000;"> intParameter.ToString(); <br />}</span></div></pre></div></p><br /><p>Greetz, G</p>GSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.com15tag:blogger.com,1999:blog-6664599031383909915.post-49881823556500582012007-04-18T07:15:00.001+00:002007-04-18T07:17:17.899+00:00Serializing viewstate to object<p>In an earlier article, concerning a <a href="http://gsharper.blogspot.com/2007/03/aspnet-20-wizard-combined-with-state.html">refactoring to a State machine</a>, I stated the problem of passing the entire viewstate to the state machine because of the need for some viewstate items. </p><p>Actually I needed a total of 5 viewstate items. So passing the entire viewstate was definitely not a good idea. After reading some stuff about serialization I solved the problem. </p><p>Let me explain the steps.</p><ul><li>Create an class which contains the needed properties </li><li>Override LoadViewState and SaveViewState in the page</li><li>Load the object from the viewstate in LoadViewState</li><li>Save the object in SaveViewState</li><li>Pass the object into the state machine instead of the actual viewstate</li></ul><p>This is how the code looks like:</p><p></p><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:8341c1f8-246a-4e3a-88aa-bd1a0e036e3e" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; WIDTH: 446px; PADDING-TOP: 0px"><pre style="FONT-SIZE: 80%; WIDTH: 100%; BACKGROUND-COLOR: #eeeeee"><span style="color:#000000;">[Serializable]<br /></span><span style="color:#0000ff;">public</span><span style="color:#000000;"> </span><span style="color:#0000ff;">class</span><span style="color:#000000;"> MyOwnViewState<br />{<br /></span><span style="color:#0000ff;">private</span><span style="color:#000000;"> Object _myViewStateField;<br /><br /></span><span style="color:#0000ff;">public</span><span style="color:#000000;"> Object MyViewStateProperty<br />{<br /></span><span style="color:#0000ff;">get</span><span style="color:#000000;"> { </span><span style="color:#0000ff;">return</span><span style="color:#000000;"> _myViewStateField; }<br /></span><span style="color:#0000ff;">set</span><span style="color:#000000;"> { _myViewStateField </span><span style="color:#000000;">=</span><span style="color:#000000;"> value; }<br />}<br />}</span><br /></pre></div><p></p><br /><p>Notice the [Serializable] attribute. </p><br /><p>Next we override the Loading and Saving of the viewstate.</p><br /><p><br /></p><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:c4c047ca-164a-483b-9276-e9735500e677" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; WIDTH: 444px; PADDING-TOP: 0px"><pre style="FONT-SIZE: 80%; WIDTH: 100%; BACKGROUND-COLOR: #eeeeee"><span style="color:#0000ff;">protected</span><span style="color:#000000;"> </span><span style="color:#0000ff;">override</span><span style="color:#000000;"> </span><span style="color:#0000ff;">void</span><span style="color:#000000;"> LoadViewState(</span><span style="color:#0000ff;">object</span><span style="color:#000000;"> savedState)<br />{<br /></span><span style="color:#0000ff;">if</span><span style="color:#000000;"> (savedState </span><span style="color:#000000;">!=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">null</span><span style="color:#000000;">)<br />{<br /></span><span style="color:#0000ff;">object</span><span style="color:#000000;">[] myState </span><span style="color:#000000;">=</span><span style="color:#000000;"> (</span><span style="color:#0000ff;">object</span><span style="color:#000000;">[])savedState;<br /><br /></span><span style="color:#0000ff;">if</span><span style="color:#000000;"> (myState[</span><span style="color:#800080;">0</span><span style="color:#000000;">] </span><span style="color:#000000;">!=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">null</span><span style="color:#000000;">)<br /></span><span style="color:#0000ff;">base</span><span style="color:#000000;">.LoadViewState(myState[</span><span style="color:#800080;">0</span><span style="color:#000000;">]);<br /><br /></span><span style="color:#0000ff;">if</span><span style="color:#000000;"> (myState[</span><span style="color:#800080;">1</span><span style="color:#000000;">] </span><span style="color:#000000;">!=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">null</span><span style="color:#000000;">)<br />_myOwnViewState </span><span style="color:#000000;">=</span><span style="color:#000000;"> (MyOwnViewState)myState[</span><span style="color:#800080;">1</span><span style="color:#000000;">];<br />}<br />}</span><br /></pre></div><p></p><br /><p>First we check if the viewstate isn't null. Next we put the it in an object array. Finally we pull the custom object out of the object array and put it in a private field so we can use it.</p><br /><p>Saving works in a similar way</p><br /><p><br /></p><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:0e8bf29b-4474-47e1-84e4-a91d7d75120f" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; WIDTH: 443px; PADDING-TOP: 0px"><pre style="FONT-SIZE: 80%; WIDTH: 100%; BACKGROUND-COLOR: #eeeeee"><span style="color:#0000ff;">protected</span><span style="color:#000000;"> </span><span style="color:#0000ff;">override</span><span style="color:#000000;"> </span><span style="color:#0000ff;">object</span><span style="color:#000000;"> SaveViewState()<br />{<br /></span><span style="color:#0000ff;">object</span><span style="color:#000000;"> baseState </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">base</span><span style="color:#000000;">.SaveViewState();<br /></span><span style="color:#0000ff;">object</span><span style="color:#000000;">[] allStates </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> </span><span style="color:#0000ff;">object</span><span style="color:#000000;">[</span><span style="color:#800080;">3</span><span style="color:#000000;">];<br />allStates[</span><span style="color:#800080;">0</span><span style="color:#000000;">] </span><span style="color:#000000;">=</span><span style="color:#000000;"> baseState;<br />allStates[</span><span style="color:#800080;">1</span><span style="color:#000000;">] </span><span style="color:#000000;">=</span><span style="color:#000000;"> _myOwnViewState;<br /></span><span style="color:#0000ff;">return</span><span style="color:#000000;"> allStates;<br />}</span><br /></pre></div><p></p><br /><p>We save the state as a cumulative array of objects. And we add our custom object to the array. </p><br /><p>The only thing that's left is use the custom object in the state machine</p><br /><p><br /></p><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:36604c1b-99cc-4a37-ac6b-22438ec45a72" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; WIDTH: 442px; PADDING-TOP: 0px"><pre style="WIDTH: 100%; BACKGROUND-COLOR: #eeeeee"><span style="color:#000000;">WizardFlowControl wizardFlowControl </span><span style="color:#000000;">=</span><span style="color:#000000;"><br /></span><span style="color:#0000ff;">new</span><span style="color:#000000;"> WizardFlowControl(_wizardControl, _myOwnViewState);<br /><br />wizardFlowControl.Handle();</span><br /></pre></div><p></p><br /><p>That's it. Greetz, G</p>GSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.com0tag:blogger.com,1999:blog-6664599031383909915.post-60778895789905052272007-04-13T07:32:00.001+00:002007-04-13T07:32:35.371+00:00No more custom section handlers in .NET 2.0<p>With the framework 2.0 we don't need to write custom section handlers for the web.config file anymore. </p> <p>Now there are property settings we can use. </p> <p>Choose the project properties. Then select Settings. There we fill in the key/value pairs. Choose Application for the scope and save. </p> <p>Now VS has created an app.config file in the project. In the app.config file there's a section group with a section defined in it. There's also an application settings section in it.</p> <p>Copy section to the section group in the web.config file. Copy the application settings section also to the web.config file.</p> <p>Delete the app.config file. </p> <p>Now lets call the settings in your code like this</p> <p> <div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:ec62b832-02ca-4225-8fdc-81783c4fb9a8" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; width: 447px; padding-top: 0px"><pre style="width:100%;background-color:#EEEEEE;"><div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF;">string</span><span style="color: #000000;"> mySetting </span><span style="color: #000000;">=</span><span style="color: #000000;"> <br />Properties.Settings.Default.MySetting;</span></div></pre></div></p><br /><p>When you want to get a setting dynamically, use this code</p><br /><p><br /><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:9717e8e6-8735-442d-88ec-030b50eaca0f" contenteditable="false" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; width: 448px; padding-top: 0px"><pre style="width:100%;background-color:#EEEEEE;"><div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF;">object</span><span style="color: #000000;"> myDynamicSetting </span><span style="color: #000000;">=</span><span style="color: #000000;"> Properties.Settings.Default.Properties[MyDynamicSettingsKey].DefaultValue;</span></div></pre></div></p><br /><p>Greetz, G</p>GSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.com1tag:blogger.com,1999:blog-6664599031383909915.post-76205302495846878762007-03-30T12:36:00.000+00:002007-03-30T12:44:25.565+00:00Substrings with regular expressionHi,<br><br>since I always forget this one, I'll post it here.<br><br>I'm tired of always using native c# code to perform substring selects on string values. This produces lots of code. I've replaced it with regular expressions<br><br>Let's suppose we have the following string value<br><br>string expr = "This is a test message where I want to extract the value test out of [test]";<br><br>We can use this code:<br><br>string value=<br>Regex.Match(expr ,@"(?<=\[).*(?=\])").Value;<br><br>value will be test !!GSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.com10tag:blogger.com,1999:blog-6664599031383909915.post-68942200689823477542007-03-30T12:35:00.001+00:002007-04-03T10:40:37.525+00:00Conditional dispatcher to Command Pattern<p>Some time ago, a customer asked me for a solution for the following problem:</p><p>They had to send messages to certain people. These messages where kept in a database table. The messages contained variables which had to be filled in by the person who sends the message. For example:</p><p>I will be [NumberInput] minutes late. </p><p>You need to make a delivery to address [AddressList]. </p><p>Please call telephone number [TelephoneList].</p><p>When the operator selects the first message, a textbox is shown where he has to input a delay.</p><p>When the second message is selected, a combobox will be shown containing addresses.</p><p>When the third message is selected, a listbox will be shown containing telephone numbers.</p><p>So I created a little application which retrieved the messages from the database in a Combobox. When selecting one of the messages, the following code runs</p><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:6aaec669-97e9-48f9-a3ab-edc86c3ef62e" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; WIDTH: 443px; PADDING-TOP: 0px"><pre style="FONT-SIZE: 80%; WIDTH: 100%; BACKGROUND-COLOR: #eeeeee"><span style="color:#000000;">Label lblTitle;<br /></span><span style="color:#0000ff;">if</span><span style="color:#000000;"> (messageSelector.SelectedItem.ToString().IndexOf(</span><span style="color:#800000;">"</span><span style="color:#800000;">NumberInput</span><span style="color:#800000;">"</span><span style="color:#000000;">) </span><span style="color:#000000;">!=</span><span style="color:#000000;"> </span><span style="color:#000000;">-</span><span style="color:#800080;">1</span><span style="color:#000000;">)<br />{<br />Label lblTitle </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> Label();<br />lblTitle.Text </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#800000;">"</span><span style="color:#800000;">Input Number</span><span style="color:#800000;">"</span><span style="color:#000000;"><br />messagePanel.Controls.Clear();<br />TextBox txtNumberInput </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> TextBox();<br />txtNumberInput.Name </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#800000;">"</span><span style="color:#800000;">NumberInput</span><span style="color:#800000;">"</span><span style="color:#000000;"><br />messagePanel.Controls.Add(lblTitle);<br />txtNumberInput.Width </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#800080;">120</span><span style="color:#000000;">;<br />txtNumberInput.Location </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> Point(</span><span style="color:#800080;">100</span><span style="color:#000000;">, </span><span style="color:#800080;">0</span><span style="color:#000000;">);<br />messagePanel.Controls.Add(txtNumberInput);<br />}<br /></span><span style="color:#0000ff;">else</span><span style="color:#000000;"> </span><span style="color:#0000ff;">if</span><span style="color:#000000;"> (messageSelector.SelectedItem.ToString().IndexOf(</span><span style="color:#800000;">"</span><span style="color:#800000;">AddressList</span><span style="color:#800000;">"</span><span style="color:#000000;">) </span><span style="color:#000000;">!=</span><span style="color:#000000;"> </span><span style="color:#000000;">-</span><span style="color:#800080;">1</span><span style="color:#000000;">)<br />{<br />Label lblTitle </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> Label();<br />lblTitle.Text </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#800000;">"</span><span style="color:#800000;">Choose Address</span><span style="color:#800000;">"</span><span style="color:#000000;"><br />messagePanel.Controls.Clear();<br />ComboBox cmbAdressList </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> ComboBox();<br />cmbAdressList.Name </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#800000;">"</span><span style="color:#800000;">AddressList</span><span style="color:#800000;">"</span><span style="color:#000000;"><br /></span><span style="color:#008000;">//</span><span style="color:#008000;"> Get addresses from the database.</span><span style="color:#008000;"><br /></span><span style="color:#000000;">GetAddresses(cmbAdressList);<br />messagePanel.Controls.Add(lblTitle);<br />cmbAdressList.Width </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#800080;">120</span><span style="color:#000000;">;<br />cmbAdressList.Location </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> Point(</span><span style="color:#800080;">100</span><span style="color:#000000;">, </span><span style="color:#800080;">0</span><span style="color:#000000;">);<br />messagePanel.Controls.Add(cmbAdressList);<br />}<br /></span><span style="color:#0000ff;">else</span><span style="color:#000000;"> </span><span style="color:#0000ff;">if</span><span style="color:#000000;"> (messageSelector.SelectedItem.ToString().IndexOf(</span><span style="color:#800000;">"</span><span style="color:#800000;">TelephoneList</span><span style="color:#800000;">"</span><span style="color:#000000;">) </span><span style="color:#000000;">!=</span><span style="color:#000000;"> </span><span style="color:#000000;">-</span><span style="color:#800080;">1</span><span style="color:#000000;">)<br />{<br />Label lblTitle </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> Label();<br />lblTitle.Text </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#800000;">"</span><span style="color:#800000;">Choose Telephone</span><span style="color:#800000;">"</span><span style="color:#000000;"><br />messagePanel.Controls.Clear();<br />ListBox lstTelephoneList </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> ListBox();<br />lstTelephoneList.Name </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#800000;">"</span><span style="color:#800000;">TelephoneList</span><span style="color:#800000;">"</span><span style="color:#000000;"><br /></span><span style="color:#008000;">//</span><span style="color:#008000;"> Get telephone numbers from the database.</span><span style="color:#008000;"><br /></span><span style="color:#000000;">GetTelephoneNumbers(lstTelephoneList);<br />messagePanel.Controls.Add(lblTitle);<br />lstTelephoneList.Width </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#800080;">120</span><span style="color:#000000;">;<br />lstTelephoneList.Location </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> Point(</span><span style="color:#800080;">100</span><span style="color:#000000;">, </span><span style="color:#800080;">0</span><span style="color:#000000;">);<br />messagePanel.Controls.Add(lstTelephoneList);<br />}<br /></span><br /></pre></div>This is definitely a violation of the open-closed principle. And duplicate code? A lot of it.<br /><p>But the customer wanted a quick solution and they said no other messages will be added with different controls. One week later, a new message was added :)</p><br /><p>Please call telephone number [TelephoneInput].</p><br /><p>This message resulted in a special textbox GsmNumberTextBox which did some extra validations using regular expressions.</p><br /><p>So, I could add another conditional statement but I was sure that there would be additional messages in the future. So time to change some stuff.</p><br /><p>I read an article, "Replace conditional dispatcher with command pattern". </p><br /><p>First I would do the refactor step "Extract Method":</p><br /><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:e5535e10-5e5c-4faf-8458-d0138ebadc1a" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; WIDTH: 441px; PADDING-TOP: 0px"><pre style="FONT-SIZE: 80%; WIDTH: 100%; BACKGROUND-COLOR: #eeeeee"><span style="color:#0000ff;">if</span><span style="color:#000000;"> (messageSelector.SelectedItem.ToString().IndexOf(</span><span style="color:#800000;">"</span><span style="color:#800000;">NumberInput</span><span style="color:#800000;">"</span><span style="color:#000000;">) </span><span style="color:#000000;">!=</span><span style="color:#000000;"> </span><span style="color:#000000;">-</span><span style="color:#800080;">1</span><span style="color:#000000;">)<br />{<br />ShowNumberInput();<br />}<br /></span><span style="color:#0000ff;">else</span><span style="color:#000000;"> </span><span style="color:#0000ff;">if</span><span style="color:#000000;"> (...)<br /><br /></span><span style="color:#0000ff;">private</span><span style="color:#000000;"> Label ShowNumberInput()<br />{<br />Label lblTitle;<br />lblTitle </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> Label();<br />lblTitle.Text </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#800000;">"</span><span style="color:#800000;">Input Number</span><span style="color:#800000;">"</span><span style="color:#000000;"><br />messagePanel.Controls.Clear();<br />TextBox txtNumberInput </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> TextBox();<br />txtNumberInput.Name </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#800000;">"</span><span style="color:#800000;">NumberInput</span><span style="color:#800000;">"</span><span style="color:#000000;"><br />messagePanel.Controls.Add(lblTitle);<br />txtNumberInput.Width </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#800080;">120</span><span style="color:#000000;">;<br />txtNumberInput.Location </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> Point(</span><span style="color:#800080;">100</span><span style="color:#000000;">, </span><span style="color:#800080;">0</span><span style="color:#000000;">);<br />messagePanel.Controls.Add(txtNumberInput);<br /></span><span style="color:#0000ff;">return</span><span style="color:#000000;"> lblTitle;<br />}<br /></span><br /></pre></div>I do the same for the other conditional steps.<br /><p>The next refactor step is "Extract class":</p><br /><p><br /></p><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:0ac4ebb9-fd9a-4a83-b2da-fd1807be7aa6" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; WIDTH: 440px; PADDING-TOP: 0px"><pre style="FONT-SIZE: 80%; WIDTH: 100%; BACKGROUND-COLOR: #eeeeee"><span style="color:#0000ff;">class</span><span style="color:#000000;"> NumberInputTextBox<br />{<br />TextBox _txtNumberInput;<br /><br /></span><span style="color:#0000ff;">public</span><span style="color:#000000;"> NumberInputTextBox()<br />{<br />_txtNumberInput </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> TextBox();<br />}<br /><br /></span><span style="color:#0000ff;">public</span><span style="color:#000000;"> Control CreateNumberInput()<br />{<br />Control control </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> UserControl();<br />control.Width </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#800080;">276</span><span style="color:#000000;">;<br />Label lblTitle;<br />lblTitle </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> Label();<br />lblTitle.Text </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#800000;">"</span><span style="color:#800000;">Input Number</span><span style="color:#800000;">"</span><span style="color:#000000;"><br />_txtNumberInput.Name </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#800000;">"</span><span style="color:#800000;">NumberInput</span><span style="color:#800000;">"</span><span style="color:#000000;"><br />control.Controls.Add(lblTitle);<br />_txtNumberInput.Width </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#800080;">120</span><span style="color:#000000;">;<br />_txtNumberInput.Location </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> Point(</span><span style="color:#800080;">100</span><span style="color:#000000;">, </span><span style="color:#800080;">0</span><span style="color:#000000;">);<br />control.Controls.Add(_txtNumberInput);<br /></span><span style="color:#0000ff;">return</span><span style="color:#000000;"> control;<br />}<br /><br /></span><span style="color:#0000ff;">public</span><span style="color:#000000;"> </span><span style="color:#0000ff;">string</span><span style="color:#000000;"> Text<br />{<br /></span><span style="color:#0000ff;">get</span><span style="color:#000000;"> { </span><span style="color:#0000ff;">return</span><span style="color:#000000;"> _txtNumberInput.Text; }<br /></span><span style="color:#0000ff;">set</span><span style="color:#000000;"> { _txtNumberInput.Text </span><span style="color:#000000;">=</span><span style="color:#000000;"> value;}<br />}<br />}<br /></span><br /></pre></div>I create a NumberInputTextBox and move all the code from the ShowNumberInput method to a public class method CreateNumberInput. The Text property has to be exposed so I create a public property. In the CreateNumberInput method I create some sort of placeholder named control which I decorate with the necessary controls. <p></p><br /><p>I do the same for the other conditional steps. So now we have three classes.</p><br /><p>Now I change the conditional steps to call the new classes and I also remove the call to the old ShowNumberInput method.</p><br /><p><br /></p><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:0f56fcd0-30c2-4c74-8ce2-5e38310a6cd5" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; WIDTH: 440px; PADDING-TOP: 0px"><pre style="FONT-SIZE: 80%; WIDTH: 100%; BACKGROUND-COLOR: #eeeeee"><span style="color:#0000ff;">if</span><span style="color:#000000;"> (messageSelector.SelectedItem.ToString().IndexOf(</span><span style="color:#800000;">"</span><span style="color:#800000;">NumberInput</span><span style="color:#800000;">"</span><span style="color:#000000;">) </span><span style="color:#000000;">!=</span><span style="color:#000000;"> </span><span style="color:#000000;">-</span><span style="color:#800080;">1</span><span style="color:#000000;">)<br />{<br />messagePanel.Controls.Clear();<br /><br />NumberInputTextBox numberInputTextBox </span><span style="color:#000000;">=</span><span style="color:#000000;"><br /></span><span style="color:#0000ff;">new</span><span style="color:#000000;"> NumberInputTextBox();<br /><br />messagePanel.Controls.Add<br />(numberInputTextBox.CreateNumberInput());<br />}<br /></span><span style="color:#0000ff;">else</span><span style="color:#000000;"> </span><span style="color:#0000ff;">if</span><span style="color:#000000;"> (...)<br /></span><br /></pre></div>I apply the step "Extract Interface" on the classes. I have to decide a common command execution method name. Now we have : <p></p><br /><ul><br /><li>CreateNumberInput<br /><li>CreateAddressListBoxCombo<br /><li>CreateTelephoneListBox</li></ul><br /><p>Let's change these names to <strong>CreateParameterControl</strong> and create the interface:</p><br /><p><br /></p><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:2475b24c-fcfa-434f-9ba2-0de99a71fb71" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; WIDTH: 442px; PADDING-TOP: 0px"><pre style="FONT-SIZE: 80%; WIDTH: 100%; BACKGROUND-COLOR: #eeeeee"><span style="color:#0000ff;">public</span><span style="color:#000000;"> </span><span style="color:#0000ff;">interface</span><span style="color:#000000;"> IHandler<br />{<br />Control CreateParameterControl();<br />}<br /></span><br /></pre></div>Let the parameter classes implement IHandler. Now every class' Create... method is renamed to CreateParameterControl.<br /><p>The next step is to change the calls in the conditional statements to the new CreateParameterControl method.</p><br /><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:60764ae2-0bd0-4b87-b6b3-8e7f155ff72d" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; WIDTH: 437px; PADDING-TOP: 0px"><pre style="FONT-SIZE: 80%; WIDTH: 100%; BACKGROUND-COLOR: #eeeeee"><span style="color:#0000ff;">if</span><span style="color:#000000;"> (messageSelector.SelectedItem.ToString().IndexOf(</span><span style="color:#800000;">"</span><span style="color:#800000;">NumberInput</span><span style="color:#800000;">"</span><span style="color:#000000;">) </span><span style="color:#000000;">!=</span><span style="color:#000000;"> </span><span style="color:#000000;">-</span><span style="color:#800080;">1</span><span style="color:#000000;">)<br />{<br />messagePanel.Controls.Clear();<br /><br />NumberInputTextBox numberInputTextBox </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">new</span><span style="color:#000000;"><br />NumberInputTextBox();<br /><br />messagePanel.Controls.Add(numberInputTextBox.CreateParameterControl());<br />}</span><br /></pre></div><br /><p>Now we have a couple of different solutions to go further with the refactoring:</p><br /><ul><br /><li>Create a Command map and fill it with key value pairs being the name of the parameter to create and the resulting parameter class.<br /><li>Create a Factory which uses reflection (see my article <a href="http://gsharper.blogspot.com/2007/03/creating-instances-using-reflection.html">Reflection instances</a> ) to let a config file decide which parameter requires which control.</li></ul><br /><p><strong>First let's see how the the Command map solution works:</strong></p><br /><p>First of all we create a map. I'll use a generic dictionary for it like this:</p><br /><p><br /></p><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:dc8a3e2c-078c-430d-b8e4-fa8661e33432" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; WIDTH: 437px; PADDING-TOP: 0px"><pre style="FONT-SIZE: 80%; WIDTH: 100%; BACKGROUND-COLOR: #eeeeee"><span style="color:#000000;">IDictionary</span><span style="color:#000000;"><</span><span style="color:#0000ff;">string</span><span style="color:#000000;">,Control</span><span style="color:#000000;">></span><span style="color:#000000;"> _paramCreationMap;</span><br /></pre></div>During initialization we fill the map: <p></p><br /><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:29b4f739-e2e9-4456-a61c-8d333ef682be" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; WIDTH: 438px; PADDING-TOP: 0px"><pre style="FONT-SIZE: 80%; WIDTH: 100%; BACKGROUND-COLOR: #eeeeee"><span style="color:#0000ff;">private</span><span style="color:#000000;"> </span><span style="color:#0000ff;">void</span><span style="color:#000000;"> CreateHandlerMap()<br />{<br />_paramCreationMap </span><span style="color:#000000;">=</span><span style="color:#000000;"> </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> Dictionary</span><span style="color:#000000;"><</span><span style="color:#0000ff;">string</span><span style="color:#000000;">,Control</span><span style="color:#000000;">></span><span style="color:#000000;">();<br />_paramCreationMap.Add(</span><span style="color:#800000;">"</span><span style="color:#800000;">NumberInput</span><span style="color:#800000;">"</span><span style="color:#000000;">, </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> NumberInputTextBox().CreateParameterControl());<br />_paramCreationMap.Add(</span><span style="color:#800000;">"</span><span style="color:#800000;">AddressList</span><span style="color:#800000;">"</span><span style="color:#000000;">, </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> AddressListComboBox().CreateParameterControl());<br />_paramCreationMap.Add(</span><span style="color:#800000;">"</span><span style="color:#800000;">TelephoneList</span><span style="color:#800000;">"</span><span style="color:#000000;">, </span><span style="color:#0000ff;">new</span><span style="color:#000000;"> TelephoneListBox().CreateParameterControl());<br />}<br /></span><br /></pre></div>the previous conditional dispatcher, can now be completely removed and replaced with this code:<br /><p><br /></p><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:86080728-6d19-49a8-8683-f7f05e51f8e6" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; WIDTH: 437px; PADDING-TOP: 0px"><pre style="FONT-SIZE: 80%; WIDTH: 100%; BACKGROUND-COLOR: #eeeeee"><span style="color:#008000;">//</span><span style="color:#008000;"> Get the param string out of the selectedItem using reflection</span><span style="color:#008000;"><br /></span><span style="color:#0000ff;">string</span><span style="color:#000000;"> paramName </span><span style="color:#000000;">=</span><span style="color:#000000;"> Regex.Match(messageSelector.SelectedItem.ToString(), </span><span style="color:#800000;">@"</span><span style="color:#800000;">(?<=\[).*(?=\])</span><span style="color:#800000;">"</span><span style="color:#000000;">).Value;<br />messagePanel.Controls.Clear();<br />Control paramControl </span><span style="color:#000000;">=</span><span style="color:#000000;"> _paramCreationMap[paramName];<br />messagePanel.Controls.Add(paramControl);<br /></span><br /></pre></div>So no more conditional if...then...else...else if... or switch case statements. <p></p><br /><p><strong>Now, lets look at the second solution:</strong></p><br /><p>The result I'm trying to achieve is to get rid of the filling of a map with instances. Because when a new control is created, the instance has to be added to the map which I don't particularly like. </p><br /><p>Then, a friend of mine showed me the beauty of reflection. I created my reflection based factory like this:</p><br /><p><br /></p><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:1399fcf0-b2f6-469b-b4df-30a8314baaaa" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; WIDTH: 436px; PADDING-TOP: 0px"><pre style="FONT-SIZE: 80%; WIDTH: 100%; BACKGROUND-COLOR: #eeeeee"><span style="color:#0000ff;">public</span><span style="color:#000000;"> </span><span style="color:#0000ff;">static</span><span style="color:#000000;"> </span><span style="color:#0000ff;">class</span><span style="color:#000000;"> ParameterFactory<br />{<br /></span><span style="color:#0000ff;">public</span><span style="color:#000000;"> </span><span style="color:#0000ff;">static</span><span style="color:#000000;"> Control CreateParameter(</span><span style="color:#0000ff;">string</span><span style="color:#000000;"> paramName)<br />{<br /></span><span style="color:#0000ff;">string</span><span style="color:#000000;"> assemblyName </span><span style="color:#000000;">=</span><span style="color:#000000;"><br />ConfigurationManager.AppSettings[</span><span style="color:#800000;">"</span><span style="color:#800000;">ParameterControlsProject</span><span style="color:#800000;">"</span><span style="color:#000000;">];<br /><br /></span><span style="color:#0000ff;">string</span><span style="color:#000000;"> typeToLoad </span><span style="color:#000000;">=</span><span style="color:#000000;"><br />ConfigurationManager.AppSettings[paramName];<br /><br />ObjectHandle objectHandle </span><span style="color:#000000;">=</span><span style="color:#000000;"><br />Activator.CreateInstance(assemblyName,typeToLoad);<br /><br />IHandler parameter </span><span style="color:#000000;">=</span><span style="color:#000000;"> (IHandler)objectHandle.Unwrap();<br />Control control </span><span style="color:#000000;">=</span><span style="color:#000000;"> parameter.CreateParameterControl();<br />control.Name </span><span style="color:#000000;">=</span><span style="color:#000000;"> typeToLoad;<br /><br /></span><span style="color:#0000ff;">return</span><span style="color:#000000;"> control;<br />}<br />}<br /></span><br /></pre></div>The factory gets called like this: <p></p><br /><p><br /></p><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:9cea873e-04c9-4507-90e4-8df7ee835133" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; WIDTH: 437px; PADDING-TOP: 0px"><pre style="FONT-SIZE: 80%; WIDTH: 100%; BACKGROUND-COLOR: #eeeeee"><span style="color:#008000;">//</span><span style="color:#008000;"> Get the param string out of the selectedItem using reflection</span><span style="color:#008000;"><br /></span><span style="color:#0000ff;">string</span><span style="color:#000000;"> paramName </span><span style="color:#000000;">=</span><span style="color:#000000;"><br />Regex.Match(messageSelector.SelectedItem.ToString(), </span><span style="color:#800000;">@"</span><span style="color:#800000;">(?<=\[).*(?=\])</span><span style="color:#800000;">"</span><span style="color:#000000;">).Value;<br /><br />messagePanel.Controls.Clear();<br /><br />Control paramControl </span><span style="color:#000000;">=</span><span style="color:#000000;"> ParameterFactory.CreateParameter(paramName);<br /><br />messagePanel.Controls.Add(paramControl);<br /></span><br /></pre></div>In the config file, in the AppSettings section we declare some key-value pairs which specify, which paramName corresponds with which type to load: <p></p><br /><p><br /><p><br /></p><div class="wlWriterSmartContent" id="F2210F5F-69EB-4d4c-AFF7-B8A050E9CC72:3d69241b-6cd3-45c4-b5a6-e94fc37cb9fa" contenteditable="false" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; WIDTH: 440px; PADDING-TOP: 0px"><pre style="FONT-SIZE: 80%; WIDTH: 100%; BACKGROUND-COLOR: #eeeeee"><span style="color:#000000;"><</span><span style="color:#000000;">appSettings</span><span style="color:#000000;">></span><span style="color:#000000;"><br /></span><span style="color:#000000;"><</span><span style="color:#000000;">add key</span><span style="color:#000000;">=</span><span style="color:#800000;">"</span><span style="color:#800000;">ParameterControlsProject</span><span style="color:#800000;">"</span><span style="color:#000000;"> value </span><span style="color:#000000;">=</span><span style="color:#800000;">"</span><span style="color:#800000;">ParameterControls</span><span style="color:#800000;">"</span><span style="color:#000000;">></</span><span style="color:#000000;">add</span><span style="color:#000000;">></span><span style="color:#000000;"><br /></span><span style="color:#000000;"><</span><span style="color:#000000;">add key</span><span style="color:#000000;">=</span><span style="color:#800000;">"</span><span style="color:#800000;">NumberInput</span><span style="color:#800000;">"</span><span style="color:#000000;"> value </span><span style="color:#000000;">=</span><span style="color:#800000;">"</span><span style="color:#800000;">ParameterControls.NumberInputTextBox</span><span style="color:#800000;">"</span><span style="color:#000000;">></</span><span style="color:#000000;">add</span><span style="color:#000000;">></span><span style="color:#000000;"><br /></span><span style="color:#000000;"><</span><span style="color:#000000;">add key</span><span style="color:#000000;">=</span><span style="color:#800000;">"</span><span style="color:#800000;">AddressList</span><span style="color:#800000;">"</span><span style="color:#000000;"> value </span><span style="color:#000000;">=</span><span style="color:#800000;">"</span><span style="color:#800000;">ParameterControls.AddressListComboBox</span><span style="color:#800000;">"</span><span style="color:#000000;">></</span><span style="color:#000000;">add</span><span style="color:#000000;">></span><span style="color:#000000;"><br /></span><span style="color:#000000;"><</span><span style="color:#000000;">add key</span><span style="color:#000000;">=</span><span style="color:#800000;">"</span><span style="color:#800000;">TelephoneList</span><span style="color:#800000;">"</span><span style="color:#000000;"> value </span><span style="color:#000000;">=</span><span style="color:#800000;">"</span><span style="color:#800000;">ParameterControls.TelephoneListBox</span><span style="color:#800000;">"</span><span style="color:#000000;">></</span><span style="color:#000000;">add</span><span style="color:#000000;">></span><span style="color:#000000;"><br /></span><span style="color:#000000;"></</span><span style="color:#000000;">appSettings</span><span style="color:#000000;">></span><br /></pre></div><p></p><br /><p>The key corresponds with paramName. ParameterControlsProject resembles the project where the actual control classes reside. Maybe we can change this to get the name from the calling assembly or something. I'll have to try this out. </p><br /><p>That's it,</p><br /><p>Greetz, G</p>GSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.com0tag:blogger.com,1999:blog-6664599031383909915.post-10538245356543694612007-03-28T07:01:00.000+00:002007-03-29T07:31:39.274+00:00Refactoring to Null Object<p>On my holiday, I was reading the book refactoring to patterns and I came to a topic called "Introducing Null Object".<br><br>It seemed to be extremely promising for some duplicate code I wrote some time ago. Let me explain what the problem is.</p> <p>I had written code to do some actions on a logfile. Like writing, reading and more similar actions.</p> <p>The log class looked like this:</p> <p><font color="#0000ff"><strong>public class Log<br>{</strong></font></p> <blockquote> <p><br><font color="#0000ff"><strong>StreamWriter textWriter; </strong></font></p> <p><font color="#0000ff"><strong>public Log()<br>{<br>} </strong></font> <p><font color="#0000ff"><strong></strong></font> <p><font color="#0000ff"><strong>public void Write(string logMessage)<br>{<br> textWriter = new StreamWriter(@"<path>\log.txt");<br> textWriter.WriteLine(logMessage);<br>} </strong></font> <p><font color="#0000ff"><strong></strong></font> <p><font color="#0000ff"><strong>public string Read()<br>{<br> return "Some log entries";<br>} </strong></font> <p><font color="#0000ff"><strong></strong></font> <p><font color="#0000ff"><strong>public void DoSomeLogAction()<br>{} </strong></font> <p><font color="#0000ff"><strong></strong></font> <p><font color="#0000ff"><strong>public void DoSomeOtherLogAction()<br>{}</strong></font></p></blockquote> <p><br><font color="#0000ff"><strong>}</strong></font></p> <p><font color="#000000">Then I created the following service LogService:</font></p> <p><strong><font color="#0000ff">public class LogService<br>{</font></strong></p> <blockquote> <p><br><strong><font color="#0000ff">Log _log; </font></strong></p> <p><strong><font color="#0000ff">public LogService(){} </font></strong> <p><strong><font color="#0000ff"></font></strong> <p><strong><font color="#0000ff">public LogService(Log log)<br>{<br> _log = log;<br>}</font></strong></p> <p><br><strong><font color="#0000ff">public void WriteToLog(string logMessage)<br>{<br> <font color="#ff0000"> if (_log != null)<br></font> <font color="#ff0000">{<br></font> this._log.Write(logMessage);<br> <font color="#ff0000">}<br></font> <font color="#ff0000"> else<br> {<br> DoSomethingElse();<br> }<br></font>} </font></strong></p> <p><strong><font color="#0000ff">public string ReadFromLog()<br>{<br> string result="";</font></strong> <p><strong><font color="#0000ff"> <font color="#ff0000"> if (_log != null)<br></font> <font color="#ff0000">{</font><br> result = _log.Read();<br> <font color="#ff0000">}</font><br> <font color="#ff0000"> else <br> {<br> DoSomethingElse();<br> }<br></font> return result;<br>} </font></strong></p> <p><strong><font color="#0000ff">public void SomeLogAction()<br>{<br> <font color="#ff0000">if (_log != null)<br></font> <font color="#ff0000">{</font><br> _log.DoSomeLogAction();<br> <font color="#ff0000">}<br></font> <font color="#ff0000">else<br> {<br> DoSomethingElse();<br> }<br></font>} </font></strong> <p><strong><font color="#0000ff"></font></strong> <p><strong><font color="#0000ff">public void SomeOtherLogAction()<br>{<br> <font color="#ff0000"> if (_log != null)<br></font> <font color="#ff0000">{<br></font> _log.DoSomeOtherLogAction();<br> <font color="#ff0000">}<br></font> <font color="#ff0000"> else<br> {<br> DoSomethingElse();<br> }<br></font>} </font></strong> <p><strong><font color="#0000ff"></font></strong> <p><strong><font color="#0000ff">private void DoSomethingElse()<br>{}</font></strong></p></blockquote> <p><br><strong><font color="#0000ff">}</font></strong></p> <p>We can see that there's a lot of duplicate code in it. Because of the possibility that logging is not enabled, we repeatedly have to test against the null value. If we don't do this, at some point in time we will definitely going to receive some exceptions.</p> <p>Isn't it possible to reduce the duplicate code? Yes it is. By using refactoring to Null Object. This is what we have to do.</p> <p>First of all we extract an interface from the Log Class. Like this:</p> <p><font color="#0000ff"><strong>public interface ILog<br>{<br> void Write(string logMessage);<br> string Read();<br> void DoSomeLogAction();<br> void DoSomeOtherLogAction();<br>}</strong></font></p> <p> We let Log implement this interface.</p> <p>Then we create a new class NullLog and let it also implement the ILog interface. But, the difference with the Log class is that NullLog takes care of the actions when a null value is passed to the service. Like this:</p> <p><font color="#0000ff"><strong>public class NullLog : ILog<br>{<br> public NullLog()<br> {} </strong></font></p> <p><font color="#0000ff"><strong> public void Write(string logMessage)<br> {<br> DoSomethingElse();<br> } </strong></font> <p><font color="#0000ff"><strong> public string Read()<br> {<br> string result=""<br> DoSomethingElse();<br> return result;<br> } </strong></font> <p><font color="#0000ff"><strong> public void DoSomeLogAction()<br> {<br> DoSomethingElse();<br> } </strong></font> <p><font color="#0000ff"><strong> public void DoSomeOtherLogAction()<br> {<br> DoSomethingElse();<br> } </strong></font> <p><font color="#0000ff"><strong> private void DoSomethingElse()<br> {}</strong></font></p> <p><font color="#0000ff"><strong>}</strong></font></p> <p>It's also common to let the methods do nothing at all.</p> <p>Now comes the fun part. Change the LogService class to remove redundant code. Like this:</p> <p><strong><font color="#0000ff">public class LogService<br>{</font></strong></p> <blockquote> <p><br><strong><font color="#0000ff">Log _log; </font></strong></p> <p><strong><font color="#0000ff"><strike>public LogService(){}</strike> </font></strong> <p><strong><font color="#0000ff"></font></strong> <p><strong><font color="#0000ff">public LogService() : this(new NullLog()){} </font></strong></p> <p><strong><font color="#0000ff">public LogService(Log log)<br>{<br> _log = log;<br>}</font></strong></p> <p><br><strong><font color="#0000ff">public void WriteToLog(string logMessage)<br>{<br> <font color="#ff0000"><strike> if (_log != null)<br></strike></font> <font color="#ff0000"><strike>{</strike></font><br> this._log.Write(logMessage);<br> <font color="#ff0000"><strike>}</strike></font><br> <font color="#ff0000"> <strike>else</strike><br> <strike>{</strike><br> <strike>DoSomethingElse();<br></strike> <strike>}</strike><br></font>} </font></strong></p> <p><strong><font color="#0000ff">public string ReadFromLog()<br>{<br> string result="";</font></strong> <p><strong><font color="#0000ff"> <font color="#ff0000"> <strike>if (_log != null)</strike><br></font> <font color="#ff0000"><strike>{</strike></font><br> result = _log.Read();<br> <font color="#ff0000"><strike>}</strike></font><br> <font color="#ff0000"> <strike>else </strike><br> <strike>{</strike><br> <strike>DoSomethingElse();</strike><br> <strike>}<br></strike></font> return result;<br>} </font></strong></p> <p><strong><font color="#0000ff">public void SomeLogAction()<br>{<br> <font color="#ff0000"><strike>if (_log != null)</strike><br></font> <font color="#ff0000"><strike>{</strike></font><br> _log.DoSomeLogAction();<br> <font color="#ff0000"><strike>}</strike></font><br> <font color="#ff0000"><strike>else</strike><br> <strike>{<br></strike> <strike>DoSomethingElse();</strike><br> <strike>}</strike><br></font>} </font></strong> <p><strong><font color="#0000ff"></font></strong> <p><strong><font color="#0000ff">public void SomeOtherLogAction()<br>{<br> <font color="#ff0000"> <strike>if (_log != null)</strike><br></font> <font color="#ff0000"><strike>{</strike></font><br> _log.DoSomeOtherLogAction();<br> <font color="#ff0000"><strike>}</strike></font><br> <font color="#ff0000"> <strike>else</strike><br> <strike>{</strike><br> <strike>DoSomethingElse();</strike><br> <strike>}</strike><br></font>} </font></strong> <p><strong><font color="#0000ff"></font></strong> <p><strong><font color="#0000ff"><strike>private void DoSomethingElse()</strike><br><strike>{}</strike></font></strong></p></blockquote> <p><strong><font color="#0000ff">}</font></strong> <p>First of all we changed the default constructor to pass an instance of the NullLog class to the overloaded constructor. So whenever the Service is instantiated without a Log object, everything will be delegated to the NullLog object.</p> <p>Because of this change, all the null testing is redundant and can be removed.</p> <p>Finally the private method DoSomethingElse is no longer necessary and can be safely removed.</p> <p>The new ServiceLog class now looks like this:</p> <p><font color="#0000ff"><strong>public class LogService<br>{<br> private ILog _log; </strong></font> <p><font color="#0000ff"><strong> public LogService() : this(new NullLog()){} </strong></font> <p><font color="#0000ff"><strong> public LogService(ILog log)<br> {<br> _log = log; <br> } </strong></font> <p><font color="#0000ff"><strong> public void WriteToLog(string logMessage)<br> {<br> _log.Write(logMessage); <br> } </strong></font> <p><font color="#0000ff"><strong> public string ReadFromLog()<br> {<br> return _log.Read(); <br> } </strong></font> <p><font color="#0000ff"><strong> public void SomeLogAction()<br> {<br> _log.DoSomeLogAction();<br> } </strong></font> <p><font color="#0000ff"><strong> public void SomeOtherLogAction()<br> {<br> _log.DoSomeOtherLogAction();<br> }</strong></font> <p><font color="#0000ff"><strong>}</strong></font> <p>This looks a lot better doesn't it.</p> <p>Comments are always welcome.</p> <p>Greetz,</p> <p>G</p>GSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.com2tag:blogger.com,1999:blog-6664599031383909915.post-24397378091069455242007-03-25T05:26:00.000+00:002007-03-28T07:10:18.661+00:00Refactoring to patterns by Joshua Kerievsky<p>Hi,<br /><br />I've just got back from a holiday. One week holiday means read, read, read.<br /><br />So I bought and read the book "Refactoring to patterns" and this is my conclusion:</p><p>I found it not particularly easy. But it is really great. I read stuff I already did but could be improved enormously. One thing I have to say is that reading "Refactoring: Improving the Design of Existing Code" from Martin Fowler is a must before reading this one. There are a lot of pointers to Fowler's book.</p><p>Greetz,</p><p>G</p>GSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.com1tag:blogger.com,1999:blog-6664599031383909915.post-66333485949441797842007-03-15T10:56:00.001+00:002007-03-15T10:58:33.821+00:00Create Sequence/Trigger in Oracle<p>Use the following script</p><p><span style="color:#0000ff;"><strong>DROP SEQUENCE SEQNAME; </strong></span></p><p><span style="color:#0000ff;"><strong>CREATE SEQUENCE SEQNAME<br />START WITH 1<br />MAXVALUE 9999999999<br />MINVALUE 1<br />NOCYCLE<br />NOCACHE<br />NOORDER;</strong></span> <p><span style="color:#0000ff;"><strong>CREATE OR REPLACE TRIGGER TRIGGERNAME<br />BEFORE INSERT<br />ON TABLENAME<br />REFERENCING NEW AS NEW OLD AS OLD<br />FOR EACH ROW<br />BEGIN<br />SELECT SEQNAME.NEXTVAL<br />INTO :NEW.PRIMARYKEYNAME<br />FROM DUAL; </strong></span><p><span style="color:#0000ff;"><strong>EXCEPTION<br />WHEN OTHERS THEN<br />RAISE_APPLICATION_ERROR('-20000','TRIGGERNAME');<br />END;<br />/</strong></span> <p>Greetz, <p>G</p>GSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.com0tag:blogger.com,1999:blog-6664599031383909915.post-86825838913233644262007-03-14T07:57:00.000+00:002007-03-14T08:00:23.409+00:00Iterate over Cursor in OracleTo create a procedure to iterate over the records in a cursor, use the following script<br /><br /><span style="color:#3333ff;">CREATE OR REPLACE PROCEDURE CursorProc IS<br /></span><br /><span style="color:#3333ff;">CURSOR c_Cursor IS </span><br /><span style="color:#3333ff;">SELECT col1 FROM Table;</span><br /><span style="color:#3333ff;"></span><br /><span style="color:#3333ff;">col1 Table.col1%TYPE; </span><br /><span style="color:#3333ff;"></span><br /><span style="color:#3333ff;">BEGIN </span><br /><span style="color:#3333ff;"></span><br /><span style="color:#3333ff;">OPEN c_Cursor; </span><br /><span style="color:#3333ff;">FETCH c_Cursor INTO col1; </span><br /><span style="color:#3333ff;"></span><br /><span style="color:#3333ff;">WHILE c_Cursor%found loop </span><br /><span style="color:#3333ff;">dbms_output.put_line('col1 : ' col1); </span><br /><span style="color:#3333ff;"></span><br /><span style="color:#3333ff;">FETCH c_Cursor INTO col1; </span><br /><span style="color:#3333ff;">END LOOP;<br /></span><br /><span style="color:#3333ff;">CLOSE c_Cursor;</span><br /><br /><span style="color:#3333ff;">END CursorProc;</span><br /><br />Greetz,<br />GGSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.com3tag:blogger.com,1999:blog-6664599031383909915.post-35245880336086210412007-03-14T07:28:00.000+00:002007-03-25T06:03:03.320+00:00ASP.NET 2.0 Wizard and the State Design Pattern<p>Some time ago, someone asked me to create ASP.NET 2.0 application to send mails to a list of customers. </p> <p>I will give you a short explanation of the problem at hand.</p> <p>The list of customer numbers could be retrieved by following a couple of steps. </p> <p>First we have a radiobuttonlist to make an initial choice</p> <p>1. Retrieve the list of customers who where brought on by other customers.<br>2. Retrieve the list of customers who where brought on by employees.<br>3. Retrieve the list of customers who where brought on by a marketing campaign.<br>4. Select individual customer numbers from a listbox.<br>5. Input certain customer numbers.</p> <p>After step 1, 2 or 3, the retrieved list has to be shown in a grid with row checkboxes, so individual (or all) customer numbers could be selected. </p> <p>After this step, there has to be a possibility to refine the search on location. </p> <p>So after step 1, 2 and 3 we have to go to a step to show all numbers. After this step we have to go to a refinement step.<br><br>After step 4 and 5 this refining was not necessary.<br><br>In the end all steps resulted in another step where we can select a template mail or compose one on our own.<br><br>After selecting a template or compose a message on our own, we actually send the letter.</p> <p> As you can see, it's quit a conditional flow of steps. </p> <p>After I read the scenario, I was thinking of using the Wizard control and as usual I was starting to code immediately without thoroughly thinking the problem through. I think I have to do something about that but the enthusiastic me takes over every time :)<br><br>In the next button click of the wizard I came up with the<span style="color: #000000"> following code:</span><br></p> <p><font color="#0000ff"><strong>WizardSteps activeWizardStep = (WizardSteps) wizard.ActiveStepIndex;</strong></font></p> <p><strong><font color="#0000ff"></font></strong><br><strong><span style="color: #3333ff">if (activeWizardStep != WizardSteps.makeYourChoice)<br>{<br></p></span></strong> <blockquote><strong><span style="color: #3333ff">switch (activeWizardStep)<br>{<br>case WizardSteps.customerThroughCustomer:<br>case WizardSteps.customerThroughEmployee:<br>case WizardSteps.customerThroughFamily:<br>{<br>// Do some step processing<br>wizard.ActiveStepIndex = (int)WizardSteps.showCustomerNumberList;<br>break;<br>}<br>case WizardSteps.showCustomerNumberList:<br>{<br>//<br>Do some step processing<br>wizard.ActiveStepIndex = (int)WizardSteps.refineCustomerList;<br>break;<br>}<br>case WizardSteps.choiceOfCustomerNumber:<br>case WizardSteps.inputCustomerNumber:<br>case WizardSteps.refineCustomerList:<br>{<br>// Do some step processing<br>wizard.ActiveStepIndex = (int)WizardSteps.choiceOfMarketingLetter;<br>break;<br>}<br>case WizardSteps.choiceOfMarketingLetter:<br>{<br>// Do some step processing<br>wizard.ActiveStepIndex = (int)WizardSteps.sendLetter;<br>break;<br>}<br>}<br></span></strong></blockquote><br> <p><strong><span style="color: #3333ff">}<br>else<br>{<br></span></strong></p><br> <blockquote><strong><span style="color: #3333ff">switch (stepsChoice.SelectedIndex)<br>{<br>case 0:<br>{<br>wizard.ActiveStepIndex = (int)WizardSteps.customerThroughCustomer;<br>break;<br>}<br>case 1:<br>{<br>wizard.ActiveStepIndex = (int)WizardSteps.customerThroughEmployee;<br>break;<br>}<br>case 2:<br>{<br>wizard.ActiveStepIndex = (int)WizardSteps.customerThroughFamily;<br>break;<br>}<br>case 3:<br>{<br>wizard.ActiveStepIndex = (int)WizardSteps.choiceOfCustomerNumber;<br>break;<br>}<br>case 4:<br>{<br>wizard.ActiveStepIndex = (int)WizardSteps.inputCustomerNumber;<br>break;<br>}<br>}<br></span></strong></blockquote><br> <p><span style="color: #3333ff"><strong>}<br></strong></span><span style="color: #3333ff"><font color="#000000"></font></span></p> <p><span style="color: #3333ff"><font color="#000000">I used following enum for the wizard steps</font></span></p> <p><span style="color: #3333ff"><strong>public enum WizardSteps<br>{</strong></span></p><span style="color: #3333ff"><strong> <blockquote> <p><br><font color="#0000ff">UnknownStep = -1,<br>MakeYourChoiceStep = 0,<br>CustomersThroughCustomerStep = 1,<br>CustomersThroughEmployeeStep = 2,<br>CustomersThroughCampaignStep = 3,<br>ChoiceOfCustomerNumbersStep = 4,<br>InputCustomerNumbersStep = 5,<br>ShowCustomersNumberListStep = 6,<br>RefineCustomerListStep = 7,<br>ChoiceOfMarketingLetterStep = 8,<br>SendLetterStep = 9</font></p></blockquote> <p><br>}</strong></span></p> <p><br>From the moment I started writing it, it felt like smelly code. Maintenance would be horrible. Adding or moving some of the steps would become tricky. No to mention all the design principles who were being violated. Like SRP, Open Closed, and probably some more which I didn't noticed.<br><br>I got home and took my book "Head First Design Patterns". The book is actually written for the Java community but it read so appealingly, that I finished it in a couple of days. After reading some of the chapters, it hit me that maybe I could use the "State Design Pattern". The whole scenario sounded like a state machine. I took the basic principle of the pattern and altered a few things so it looked like the following:</p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAtUWRdO0w8HpdJM-IIHVjyhehgLYHAfYA6xZ9wkaEoj_BhGL0Zz5XKX3IqVfh-Men-uwknOpWWfVYDejrz2Rd6tHaaAEgrW2WVVoOEnYhhcodRBWk4B_Djke-GKvLYnkQWXHeUeVobJE/s1600-h/StateMachinesmall.jpg" target="_new" atomicselection="true"><img id="BLOGGER_PHOTO_ID_5041757353913889874" style="cursor: hand" height="232" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW4uV8cxyqDBvXhAYlnj8Q3Lfy_wiJSezK9LY_42-bfOT_anRMg4vahKUhhdqCndrHvpZ0cVNDdPJBgOC3TiIW5bgDbOzx2DpoDcbviiUMoAL5QBANW4WtsxWPsspAbdWO05CWDBmLKg0/s400/StateMachinesmall.jpg" width="442" border="0"></a><br> <p></p> <p>Click the picture if you want a sharper image.</p> <p>So what do we have here:</p> <ul> <li>WizardFlowControl: acts as the Context Object</li></ul> <p>This object delegates all the work to the correct step. The steps determine who their next step will be. The WizardFlowControl will be instantiated when the next button gets clicked. You can think of this class as the hearth. It will regulate everything.</p> <ul> <li>Step: acts as the state interface</li></ul> <p>Step is an abstract class. It receives the actual wizard and the viewstate as a statebag. The class also has an abstract readonly property StepIndex which has to be implemented by the class inheriting Step. It also contains an abstract method Handle which has to be implemented. You can access the wizard and viewstate trough some base properties.</p> <ul> <li> Implementation classes: Inherits Step</li></ul> <p></p>These classes are the actual wizardsteps. Because they inherit from the base class Step, the have to implement the property StepIndex and the method Handle. StepIndex determines the actual position in the wizard. Handle does the processing of the wizard step. <br> <p></p> <p>Let's see how we can code it. We will begin with the base class Step. It look like this: <p><strong><font color="#0000ff">public abstract class Step<br>{</font></strong></p> <blockquote> <p><br><strong><font color="#0000ff">private Wizard _wizard;<br>private Step _nextStep;<br>private StateBag _viewState; </font></strong></p> <p><strong><font color="#0000ff">public abstract int StepIndex {get;}<br>public abstract void Handle(); </font></strong> <p><strong><font color="#0000ff">public Wizard Wizard<br>{<br>get{return _wizard;}<br>set {_wizard = value;} <br>} <br>public Step NextStep<br>{<br>get {return _nextStep;}<br>set {_nextStep = value;}<br>} <br>public StateBag ViewState<br>{<br>get {return _viewState;}<br>set {_nextStep = _viewState;}<br>} </font></strong></p></blockquote> <p><br><strong><font color="#0000ff">}</font></strong></p> <p><font color="#000000">As you can see, no rocket science here. Just an abstract class with four properties, one of them abstract, and an abstract method.</font></p> <p><font color="#000000">When we take a look at one of the implementation classes, ex. CustomersThroughCustomer, it looks like this:</font></p> <p><strong><font color="#0000ff">public class CustomersThroughCustomer : Step<br>{</font></strong></p> <blockquote> <p><strong><font color="#0000ff"><br>public CustomersThroughCustomer(){} </font></strong></p> <p><strong><font color="#0000ff">public override int StepIndex<br>{get { return (int)WizardSteps.CustomersThroughCustomerStep; }<br>} </font></strong></p> <p><strong><font color="#0000ff">public override void Handle()<br>{<br></font></strong></p> <p><strong><font color="#0000ff">// Process The Step </font></strong></p> <p><strong><font color="#0000ff">// Transition to the new state<br>NextStep = new ShowCustomersNumberList(); </font></strong></p> <p><strong><font color="#0000ff">}</font></strong></p></blockquote><strong><font color="#0000ff"> <p><br>} </font></strong></p> <p><font color="#000000">A little explanation might come in handy here. The readonly StepIndex property returns us the current integer stepindex of the wizard. In the Handle method we do the actual processing. For example we can call some kind of service to get me all customers. Then this list can be bound to a listbox or some other control. After the processing, we set the nextstep. Here we are transitioning to another state.</font></p> <p><font color="#000000">But something doesn't feel right about the transitioning code. We can clearly see some tight coupling issues here. The next step instantiation just feels awkward. Maybe we can use another design pattern here.</font></p> <p>I decided to use the "Factory Design Pattern". I implemented it, using reflection, like this: </p> <p><font color="#0000ff"><strong></strong></font> <p><font color="#0000ff"><strong>public static class StepFactory<br>{ </strong></font> <blockquote> <p><strong><font color="#0000ff"></font></strong> <p><font color="#0000ff"><strong>public static Step CreateStepInstance(string stepTypeName, Wizard wizard, StateBag viewState)<br>{ </strong></font> <p><font color="#0000ff"><strong></strong></font> </p> <p><font color="#0000ff"><strong>Assembly assembly = Assembly.LoadFrom("WizardLib.dll");<br>string assemblyName = assembly.FullName; </strong></font></p> <p><font color="#0000ff"><strong>ObjectHandle wrappedStep = Activator.CreateInstance(assemblyName, stepTypeName); </strong></font> <p><font color="#0000ff"><strong></strong></font> </p> <p><font color="#0000ff"><strong>Step step = (Step)wrappedStep.Unwrap();<br>step.Wizard = wizard;<br>step.ViewState = viewState; </strong></font></p> <p><font color="#0000ff"><strong></strong></font> <p><font color="#0000ff"><strong>return step; </strong></font> <p><font color="#0000ff"><strong>}</strong></font></p></blockquote><font color="#0000ff"><strong> <p><br>} </strong></font></p> <p><font color="#000000">Note: for more information you can read my other article <a href="http://gsharper.blogspot.com/2007/03/creating-instances-using-reflection.html">Creating instances using reflection</a></font></p> <p><font color="#000000">Now that we have our factory, let's use it and change the following code:</font></p> <p><strong><font color="#0000ff">// Transition to the new state<br>NextStep = new ShowCustomersNumberList(); </font></strong></p> <p><font color="#000000">By this one:</font></p> <p><font color="#0000ff"><strong>// Transition to the new state<br>string nextStepName = Wizard.WizardSteps[(int)WizardSteps.ShowCustomersNumberListStep].ID;</strong></font></p> <p><font color="#0000ff"><strong><br>NextStep = StepFactory.CreateStepInstance(nextStepName, Wizard);</strong></font></p> <p><font color="#000000">First we retrieve the name of the ID of the next wizardstep by getting it out of the WizardStep collection using the correct enumeration WizardStep item.</font></p> <p><font color="#000000">Then we ask the factory to give us the correct next step instance. </font></p> <p><font color="#000000">Now let's take look at the heart of the wizard, the WizardFlowControl:</font></p> <p><font color="#0000ff"><strong>public class WizardFlowControl<br>{</strong></font></p> <blockquote> <p><br><font color="#0000ff"><strong>Wizard _wizard;<br>Step _activeStep;<br>StateBag _viewState; </strong></font></p> <p><font color="#0000ff"><strong>public WizardFlowControl(Wizard wizard, StateBag viewState)<br>{<br>_wizard = wizard;<br>_viewState = viewState;<br>} </strong></font></p> <p><font color="#0000ff"><strong>public void Handle()<br>{<br> ProcessStep();<br> SetNextStep();<br>} </strong></font> <p><font color="#0000ff"><strong></strong></font> </p> <p><font color="#0000ff"><strong>private void ProcessStep()<br>{<br> // Get Current Step<br> string activeStepName = _wizard.ActiveStep.ID;<br> _activeStep = StepFactory.CreateStepInstance (activeStepName, _wizard, _viewState); </strong></font></p> <p><font color="#0000ff"><strong> // Process the active step<br> _activeStep.Handle();<br>} </strong></font> <p><font color="#0000ff"><strong></strong></font> </p> <p><font color="#0000ff"><strong>private void SetNextStep()<br>{<br> _wizard.ActiveStepIndex = _activeStep.NextStep.StepIndex; <br>}</strong></font></p></blockquote> <p><br><font color="#0000ff"><strong>}</strong></font></p> <p><font color="#000000">What's going on here: The WizardFlowControl accepts the wizard and the viewstate. </font></p> <p><font color="#000000">For loose coupling I comply to the Inversion Of Control (IoC) principle by implementing the Dependency Injection pattern. This is well described by the master itself, Martin Fowler, in the following article <a title="http://www.martinfowler.com/articles/injection.html" href="http://www.martinfowler.com/articles/injection.html">http://www.martinfowler.com/articles/injection.html</a>. </font></p> <p><font color="#000000">After instantiation (in the next button click) we then call Handle. Handle will first determine the active stepindex and asks the factory for the active Step instance. It then calls the Step's Handle method and the step gets processed.</font></p> <p><font color="#000000">Finally the wizard is set to the next step, which is determined by the step itself.</font></p> <p><font color="#000000">That's actually it. </font></p> <p><strong><u>Conclusion:</u></strong></p> <p>The huge switch-case statement in the next button click of the page is now replaced by two statements:</p> <ul> <li><font color="#0000ff"><strong>WizardFlowControl wizardFlowControl = new WizardFlowControl(this.wizard, this.ViewState);</strong></font> <li><font color="#0000ff"><strong>wizardFlowControl .Handle();</strong></font></li></ul> <p>All responsibility is now handed over to the separate step implementations. <p>We someone asks me to add a step. It is easily done by creating a new class which inherits from the abstract base class Step. We can easily configure its position in the flow by setting it's stepindex to the correct step. And finally we have to decide which step is its predecessor and its successor. <p>Finally I would point out some of the issues that still bother me. <p>The fact that we have to name the step implementation classes the same as the wizard step Id's. <p>We can easily change this and use a config file to create key/value pairs for the wizardstep/step implementation combinations. <p>The second issue is related to the fact that I implemented the state design pattern in an ASP.NET web app. What about the ViewState? <p>You cannot access the ViewState from inside the step implementation classes. So I decided to pass the entire viewstate into the the step instances by providing it to the factory. This is probably not a good idea, but I didn't see an other possibility. I really needed the viewstate in the different steps. <p>If someone reads this post and has some remarks about it, please feel free to comment. I'm still in my learning phase, so I can use every help I can get. <p>Greetz, <p>G</p>GSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.com10tag:blogger.com,1999:blog-6664599031383909915.post-57571947290210411532007-03-14T07:06:00.000+00:002007-03-14T07:25:59.391+00:00Javascript Select/Unselect All CheckboxesAnother much used Javascript function is the one where we want to select/unselect a bunch of checkboxes on screen using client side scripting. Again, I inject the script in my code behind<br /><br /><span style="color:#3333ff;">private void InjectJavascript()<br />{<br />string toggleCheckboxes = </span><br /><span style="color:#3333ff;">@"<script type=""text/javascript"">function SetAllCheckBoxes(formValue, checkValue)<br />{<br />var theForm;<br />var countElements;<br />var objElements;<br /></span><br /><span style="color:#3333ff;">theForm = document.forms[formValue];<br />if(!theForm)<br />return;<br /></span><br /><span style="color:#3333ff;">objElements = theForm.getElementsByTagName('input');<br />if(!objElements)<br />return;<br /></span><br /><span style="color:#3333ff;">countElements = objElements.length;<br />// set the check value for all check boxes<br />for(var i = 0; i < countElements; i++)<br />{<br />if (objElements[i].type == 'checkbox')<br />{<br />objElements[i].checked = checkValue;<br />}<br />}<br />}<br /></script><br />";<br /></span><br /><span style="color:#3333ff;">ClientScript.RegisterClientScriptBlock(this.GetType(), "toggleCheckboxes", toggleCheckboxes);<br /></span><br /><span style="color:#3333ff;">// Wire some javascript client-side events<br />rbtnSelectAllCheckBoxes.Attributes.Add("onclick", "SetAllCheckBoxes('" + this.Form.ClientID + "',true)");<br /></span><br /><span style="color:#3333ff;">rbtnUnSelectAllCheckBoxes.Attributes.Add("onclick", "SetAllCheckBoxes('" + this.Form.ClientID + "',false)");<br />}</span><br /><br />Call this void in the Page Load.Add a couple of checkboxes and two radiobuttons to the page.<br /><br />Name the radiobuttons "rbtnSelectAllCheckBoxes" and "rbtnUnSelectAllCheckBoxes".Give it a try.<br /><br />Greetz,<br />GGSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.com3tag:blogger.com,1999:blog-6664599031383909915.post-16909303464211414842007-03-14T06:18:00.000+00:002007-03-14T07:06:03.408+00:00Javascript Select/Unselect checkbox<span style="font-family:arial;">Every time I have to use JS I get iritated because I always have to look it up on the Net. Let's put it on my blog so I can find it easier.<br /><br />The problem I had to deal with was creating a JS function to select/Unselect a checkbox. I wrote the JS function in my code behind</span><br /><br /><span style="font-family:arial;color:#3333ff;">private void InjectJavascript()<br />{<br /><br />string toggleCheckbox = @"<script type=""text/javascript""><br />function SelectUnSelectCheckBox(select)<br />{<br />var myCheckBox = document.getElementById('" + MyCheckBox.ClientID + "');";<br /></span><br /><span style="font-family:arial;color:#3333ff;">toggleCheckbox += @" myCheckBox.checked = select;<br />}</script>";</span><br /><br /><span style="font-family:arial;color:#3333ff;">// Register the javascript<br />ClientScript.RegisterClientScriptBlock(this.GetType(), "toggleCheckbox", toggleCheckbox);<br /></span><br /><span style="font-family:arial;color:#3333ff;">// Wire some javascript client-side events<br />rbtnSelectCheckBox.Attributes.Add("onclick", "SelectUnSelectCheckBox(true)");<br />rbtnUnSelectCheckBox.Attributes.Add("onclick", "SelectUnSelectCheckBox(false)");<br />}</span><br /><span style="font-family:arial;"></span><br /><span style="font-family:arial;">Call InjectJavascript in the Load of the form. Put a checkbox "MyCheckBox" and two radiobuttons "rbtnSelectCheckBox" and "rbtnUnSelectCheckBox" on the form.</span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:Arial;">That's it</span><br /><span style="font-family:Arial;"></span><br /><span style="font-family:Arial;">Greetz,</span><br /><span style="font-family:Arial;">G</span><br /><br /><br /><span style="font-family:arial;"></span>GSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.com0tag:blogger.com,1999:blog-6664599031383909915.post-71993009267845151942007-03-13T11:26:00.000+00:002007-03-14T06:24:52.956+00:00Creating instances using reflectionLet's say,<br /><br />we have a Class library, ClassLib. This library contains a type CystomType which implements a certain Interface ICustomtype. This interface defines the contract which states a method CustomMethod.<br /><br />Let's create a instance of CustomType at runtime using reflection and use the method<br /><br /><span style="color:#3333ff;"><blockquote><span style="color:#3333ff;">Assembly assembly = Assembly.LoadFrom("ClassLib.dll");<br />string assemblyName = assembly.FullName;<br />ObjectHandle wrappedCustomType =<br />Activator.CreateInstance(assemblyName,"ClassLib.CustomType");<br />ICustomType myCustomType = (ICustomType)wrappedCustomType.Unwrap();<br />myCustomType.CustomMethod();</span></blockquote></span><br /><br />Don't forget to include the following lines<br /><br /><blockquote><span style="color:#3333ff;">using System.Reflection;<br />using System.Runtime.Remoting;<br /></span></blockquote>GSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.com0tag:blogger.com,1999:blog-6664599031383909915.post-71784239170622823402007-03-13T06:04:00.000+00:002007-03-14T06:29:42.897+00:00Factory pattern extended with genericsWhen I first encountered the Factory design pattern, I was intriged. I started reading about the abstract en method versions of the pattern. I immediatly disliked the method version because of the switch case statement.<br /><br />This was obvious a violation of the open closed principle. The abstract version was beter.<br /><br />But then Generics came to the scene and I was thinking of using them to build my own GenericDaoFactory to loose couple the client code from the instantiation of my data access objects<br /><br />This is how I did it:<br /><br />I started by creating an abstract DaoBaseClass with some standard mutual CRUD methods:<br /><br /><span style="color:#3366ff;">public abstract class DaoBaseClass<dtotypeobj> <DTOTypeObj></span><br /><span style="color:#3366ff;">{ </span><br /><br /><span style="color:#3366ff;"><span style="color:#3366ff;"><blockquote><span style="color:#3366ff;"><span style="color:#3366ff;">public abstract DTOTypeObj SelectRecord(DTOTypeObj obj); </span><br /><span style="color:#3366ff;">public abstract void InsertRecord(DTOTypeObj obj); </span><br /><span style="color:#3366ff;">public abstract void UpdateRecord(DTOTypeObj obj); </span><br /><span style="color:#3366ff;">public </span></span><span style="color:#3366ff;">abstract void DeleteRecord(DTOTypeObj obj); </span></blockquote></span></span><br /><span style="color:#3366ff;">}</span><br /><br /><br />We pass in a Data Transfer Object. These objects just contain some state. Here is an example for the Customer DTO<br /><br /><span style="color:#3366ff;">public struct DTOCustomer </span><br /><span style="color:#3366ff;">{ </span><br /><br /><br /><span style="color:#3366ff;"><blockquote><p><span style="color:#3366ff;">// Add all customer transfer properties </span><br /><span style="color:#3366ff;">private int _customerNumber; </span><br /><span style="color:#3366ff;">private string _customerAccount; </span><br /><span style="color:#3366ff;">private int _id;</span></p><p><span style="color:#3366ff;"><span style="color:#3366ff;"><span style="color:#3366ff;">public int CustomerNumber </span><br /><span style="color:#3366ff;">{</span></span></span></p><span style="color:#3366ff;"><span style="color:#3366ff;"><span style="color:#3366ff;"><span style="color:#3366ff;"><blockquote><p><span style="color:#3366ff;"><span style="color:#3366ff;"><span style="color:#3366ff;"><span style="color:#3366ff;">get { return _customerNumber; } </span><br /><span style="color:#3366ff;">set </span></span><span style="color:#3366ff;">{_customerNumber = value; }</span></span></span></p></blockquote><p></span></span></span></span><span style="color:#3366ff;"><span style="color:#3366ff;"><span style="color:#3366ff;">} </span><br /><span style="color:#3366ff;"></span><br /><span style="color:#3366ff;">public string CustomerAccount </span><br /><span style="color:#3366ff;">{ </span><br /><span style="color:#3366ff;"></p><blockquote><span style="color:#3366ff;"><span style="color:#3366ff;"><span style="color:#3366ff;">get { return _customerAccount; } </span><br /><span style="color:#3366ff;">set { _customerAccount = value;</span></span></span><span style="color:#3366ff;"><span style="color:#3366ff;"><span style="color:#3366ff;">} </span></span></span></blockquote><p></span></span></span><span style="color:#3366ff;"><span style="color:#3366ff;"><span style="color:#3366ff;">} </span></p></span></span></blockquote></span><span style="color:#3366ff;">}</span><br /><br />The DTO for the employee looks simular. Now let's use the DaoBaseClass and create a DaoCustomer class:<br /><br /><span style="color:#3366ff;">public class DaoCustomer : DaoBaseClass<DTOCustomer><dtocustomer></span><br /><span style="color:#3366ff;">{</span><br /></span><span style="color:#3366ff;"><blockquote><p><span style="color:#3366ff;">public override DTOCustomer SelectRecord(DTOCustomer obj) </span><span style="color:#3366ff;">{</span></p><span style="color:#3366ff;"><blockquote><p><span style="color:#3366ff;">int customerId = obj.CustomerNumber;</span></p><p><span style="color:#3366ff;">return CustomerService.GetCustomer(obj.CustomerNumber); </span></p></blockquote><p></span><span style="color:#3366ff;">}</span></p></blockquote><p></span></p><span style="color:#3366ff;">public override void InsertRecord(DTOCustomer obj) </span><br /><span style="color:#3366ff;">{ </span><br /><p><span style="color:#3366ff;"></p></span><span style="color:#3366ff;"><blockquote><p><span style="color:#3366ff;">CustomerService.InsertCustomer(obj); </span></span></p></blockquote><span style="color:#3366ff;">}</span> <p><span style="color:#3366ff;">}</span></p><br />The other methods are left out to save some space.<br /><br />What's next? Let's create the generic factory<br /><br /><span style="color:#3366ff;">public class GenericDaoFactory<T, DTO> where T:DaoBaseClass<DTO>, new()</span><br /><span style="color:#3366ff;">{ </span><br /><span style="color:#3366ff;"><span style="color:#3366ff;"><blockquote><span style="color:#3366ff;"><span style="color:#3366ff;">private GenericDaoFactory(){} </span><br /><span style="color:#3366ff;"></span><br /><span style="color:#3366ff;">public static T CreateDaoInstance() </span><br /><span style="color:#3366ff;">{ </span></span><br /><span style="color:#3366ff;"><span style="color:#3366ff;"><span style="color:#3366ff;"><blockquote><span style="color:#3366ff;"><span style="color:#3366ff;"><span style="color:#3366ff;">T instance = new T(); </span><br /><span style="color:#3366ff;">return instance; </span></span></span></blockquote></span><br /></span><span style="color:#3366ff;">} </span><br /></span><br /></blockquote></span></span><span style="color:#3366ff;">}</span><br /><span style="color:#000000;"></span><br />The factory is quit simple. We pass in the type of daoObject we want and the factory will create an instance for us. So we are working typesafe. We also have to pass in a DTO type with which the dao object will work.<br /><br />The only thing we have to do now, is use the factory to create some Dao objects. Like this:<br /><br /><span style="color:#3366ff;">public void DoSomeStuffWithCustomersAndEmployees() </span><br /><span style="color:#3366ff;">{ </span><br /><span style="color:#3366ff;"><span style="color:#3366ff;"><span style="color:#3366ff;"><span style="color:#3366ff;"><blockquote><p><span style="color:#3366ff;"><span style="color:#3366ff;"><span style="color:#3366ff;"><span style="color:#3366ff;">DaoCustomer daoCustomer = </span></span></span></span></p><p><span style="color:#3366ff;"><span style="color:#3366ff;"><span style="color:#3366ff;"><span style="color:#3366ff;">GenericDaoFactory</span><span style="color:#3366ff;"><DaoCustomer, DTOCustomer>.CreateDaoInstance();</span></span></span></span></p><span style="color:#3366ff;"><span style="color:#3366ff;"><span style="color:#3366ff;"><p><br /><span style="color:#3366ff;">DTOCustomer dtoCustomer = new DTOCustomer(); </span><br /><span style="color:#3366ff;">dtoCustomer.CustomerNumber = 10;</span><br /><span style="color:#3366ff;">// Fill in some other data ... </span><br /><span style="color:#3366ff;">daoCustomer.InsertRecord(dtoCustomer); </span><br /><span style="color:#3366ff;"></span><br /><span style="color:#3366ff;">DaoEmployee daoEmployee = </span><br /><span style="color:#3366ff;">GenericDaoFactory<DaoEmployee, DTOEmployee>.CreateDaoInstance();</span><br /><span style="color:#3366ff;"></span></p><p><span style="color:#3366ff;">DTOEmployee dtoEmployee = new DTOEmployee(); </span><br /><span style="color:#3366ff;">dtoEmployee.EmployeeNumber = 5; </span><br /><span style="color:#3366ff;">daoEmployee.DeleteRecord(dtoEmployee); </span></span></span></span></p></blockquote></span></span><br /></span></span><span style="color:#3366ff;"><span style="color:#3366ff;"></span><br /></span><span style="color:#3366ff;"></span><span style="color:#3366ff;">}</span><br /><br />As we can see, we ask the factory to give us a DaoCustomer. It returns us the object and we can start using it. The same happens for the DaoEmployee object.<br /><br />That's it<br /><br />Comments are always welcome<br />Greetings,<br />G<br /><br /><br /><br /></span></span></span></span>GSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.com0tag:blogger.com,1999:blog-6664599031383909915.post-83878671327277983132007-03-12T20:20:00.000+00:002007-03-14T06:30:38.053+00:00Abstract classes / Abstract Methods UML 2 with Visio 2003Create an abstract class in UML<br /><br />- Go to the UML Static Structure panel and drag and drop a class on the right pane.<br />- Double click the class and select the “IsAbstract” checkbox<br /><br />The class is now abstract. You can see this on the Italic header<br /><br /><div></div><div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEip9eigzRL5xJnPCK4Fqgl99rC_fHjgx8lNv-tV7ezEbPADEZ4Pq8Eqy96Lqhrkp-mGJv8ZaB8hpHdADJx2khRhPYutl2B2lONiyPUJi3aA3dvzycAWUFP0pu5MHnyuAopPZD3g8IGgNu8/s1600-h/AbstractClass.bmp"><img id="BLOGGER_PHOTO_ID_5041136671010075650" style="CURSOR: hand" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEip9eigzRL5xJnPCK4Fqgl99rC_fHjgx8lNv-tV7ezEbPADEZ4Pq8Eqy96Lqhrkp-mGJv8ZaB8hpHdADJx2khRhPYutl2B2lONiyPUJi3aA3dvzycAWUFP0pu5MHnyuAopPZD3g8IGgNu8/s320/AbstractClass.bmp" border="0" /></a><br /></div><br /><div>Now we are going to add an abstract method<br /><br />- Double click the class, select the category operations.<br />- Press the new button.<br />- Press the method button.<br />- Unselect the “Has Method” checkbox.<br />- Select the polymorfic checkbox (it is the default)<br />- Name the operation<br /><br />We can now see the abstract method appearing. It’s also in italic. </div><br /><div></div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicFyoy7RFzY52NenmIXgDdWmc3lHKULLTxokb7SGlfvvAK_Q0MP5JrNTsMCvVOutNnqeb3xrbKcveE-2YDjT6dg0GtHjMINkyzrm508wEj4IQDRkhB0_9zX_Z_gPqWkiV_YOsVzK_cyfM/s1600-h/AbstractClassAbstractMethod.bmp"><img id="BLOGGER_PHOTO_ID_5041137504233731090" style="CURSOR: hand" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicFyoy7RFzY52NenmIXgDdWmc3lHKULLTxokb7SGlfvvAK_Q0MP5JrNTsMCvVOutNnqeb3xrbKcveE-2YDjT6dg0GtHjMINkyzrm508wEj4IQDRkhB0_9zX_Z_gPqWkiV_YOsVzK_cyfM/s320/AbstractClassAbstractMethod.bmp" border="0" /></a><br /><div></div>GSharphttp://www.blogger.com/profile/14585310431549501637noreply@blogger.com1