Fixxing invalid to date when insert into DB. And Parsing of to and from cont. page.

--- SpiritAirlineTimeTableParser/Program.cs
+++ SpiritAirlineTimeTableParser/Program.cs
@@ -11,6 +11,8 @@
 using PDFReader;
 using System.Globalization;
 using System.Text.RegularExpressions;
+using System.Data.SqlClient;
+using System.Data;

 namespace SpiritAirlineTimeTableParser
 {
@@ -27,10 +29,10 @@
             string myDirpath = AppDomain.CurrentDomain.BaseDirectory + "\\data";
             Directory.CreateDirectory(myDirpath);
             string path = AppDomain.CurrentDomain.BaseDirectory + "data\\Spirit_Timetable.pdf";
-            Uri url = new Uri("https://www.spirit.com/content/documents/en-us/timetable06AUG2015.pdf");
+            Uri url = new Uri("https://www.spirit.com/content/documents/en-us/timetable12NOV2015.pdf");
             const string ua = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)";
             const string referer = "https://www.spirit.com/RouteMaps.aspx";
-            if (!File.Exists(path))
+            if (File.Exists(path))
             {
                 WebRequest.DefaultWebProxy = null;
                 using (System.Net.WebClient wc = new WebClient())
@@ -118,10 +120,14 @@
                 validfrom = validfrom.Replace("Effective ", "");
                 //string validto = matches[1].Value;
                 DateTime ValidFrom = DateTime.ParseExact(validfrom, "MMMM d, yyyy", ci);
-                //DateTime ValidFrom = new DateTime(2015, 8, 6);
-                //DateTime ValidTo = new DateTime(2015, 11, 11);
-                //DateTime ValidFrom = DateTime.ParseExact(validfrom, "dd MMM yyyy", ci);
-                //DateTime ValidTo = DateTime.ParseExact(validto, "dd MMM yyyy", ci);
+                // Spirit airlines to date is around a month valid
+                DateTime ValidTo = ValidFrom.AddDays(30);
+
+                // To And From Can continue on the other page; So do not reset when parsing new page.
+                string TEMP_FromIATA = null;
+                string TEMP_ToIATA = null;
+
+
                 // Loop through each page of the document
                 for (var page = 2; page <= pdfReader.NumberOfPages; page++)
                 {
@@ -150,11 +156,9 @@
                                 Encoding.UTF8,
                                 Encoding.Default.GetBytes(currentText)));

-                        string[] lines = Regex.Split(currentText, "\r\n");
-                        string TEMP_FromIATA = null;
-                        string TEMP_ToIATA = null;
+                        string[] lines = Regex.Split(currentText, "\r\n");
                         DateTime TEMP_ValidFrom = ValidFrom;
-                        DateTime TEMP_ValidTo = new DateTime();
+                        DateTime TEMP_ValidTo = ValidTo;
                         int TEMP_Conversie = 0;
                         Boolean TEMP_FlightMonday = false;
                         Boolean TEMP_FlightTuesday = false;
@@ -171,7 +175,7 @@
                         TimeSpan TEMP_DurationTime = TimeSpan.MinValue;
                         Boolean TEMP_FlightNextDayArrival = false;
                         int TEMP_FlightNextDays = 0;
-                        Boolean TEMP_FlightDirect = true;
+                        Boolean TEMP_FlightDirect = true;

                         foreach (string line in lines)
                         {
@@ -203,114 +207,54 @@
                                                 TEMP_ToIATA = airport;
                                             }
                                         }
-                                    }
-                                    //// Valid from en to times
-                                    //if (String.Equals("-", temp_string) || temp_string.Substring(0, 1) == "-" || rgxdate1.Matches(temp_string).Count > 0)
-                                    //{
-                                    //    // This can be a valid from or to. Check based on temp variable min value
-                                    //    if (TEMP_ValidFrom == DateTime.MinValue)
-                                    //    {
-                                    //        if (temp_string == "-" || temp_string.Substring(0, 1) == "-") { TEMP_ValidFrom = ValidFrom; }
-                                    //        else
-                                    //        {
-                                    //            TEMP_ValidFrom = DateTime.ParseExact(rgxdate1.Matches(temp_string)[0].Value, "d MMM", ci, DateTimeStyles.None);
-                                    //        }
-                                    //    }
-                                    //    if (TEMP_ValidTo == DateTime.MinValue)
-                                    //    {
-                                    //        if (temp_string == "-" || temp_string.Substring(0, 1) == "-") { TEMP_ValidTo = ValidTo; }
-                                    //        else
-                                    //        {
-                                    //            string date2 = rgxdate1.Matches(temp_string)[1].Value;
-                                    //            TEMP_ValidTo = DateTime.ParseExact(rgxdate1.Matches(temp_string)[1].Value, "d MMM", ci, DateTimeStyles.None);
-                                    //        }
-                                    //    }
-                                    //}
+                                    }
                                     // Depart and arrival times
                                     if (rgxtime.Matches(temp_string).Count > 0)
                                     {
                                         //if (rgxtime.Matches(temp_string).Count == 2)
                                         //{
-                                            // Contains to and from date.
-                                            foreach (Match ItemMatch in rgxtime.Matches(temp_string))
-                                            {
-                                                if (TEMP_DepartTime == DateTime.MinValue)
+                                        // Contains to and from date.
+                                        foreach (Match ItemMatch in rgxtime.Matches(temp_string))
+                                        {
+                                            if (TEMP_DepartTime == DateTime.MinValue)
+                                            {
+                                                // Time Parsing
+                                                string y = ItemMatch.Value;
+                                                y = y.ToUpper();
+                                                y = y.Trim();
+                                                TEMP_DepartTime = DateTime.ParseExact(y, "h:mmt", ci);
+                                            }
+                                            else
+                                            {
+                                                // There is a from value so this is to.
+                                                string x = ItemMatch.Value;
+                                                x = x.ToUpper();
+                                                x = x.Trim();
+                                                if (x.Contains("+1"))
                                                 {
-                                                    // Time Parsing
-                                                    string y = ItemMatch.Value;
-                                                    y = y.ToUpper();
-                                                    y = y.Trim();
-                                                    TEMP_DepartTime = DateTime.ParseExact(y, "h:mmt", ci);
+                                                    // Next day arrival
+                                                    x = x.Replace("+1", "");
+                                                    TEMP_FlightNextDays = 1;
+                                                    TEMP_FlightNextDayArrival = true;
                                                 }
-                                                else
+                                                if (x.Contains("+2"))
                                                 {
-                                                    // There is a from value so this is to.
-                                                    string x = ItemMatch.Value;
-                                                    x = x.ToUpper();
-                                                    x = x.Trim();
-                                                    if (x.Contains("+1"))
-                                                    {
-                                                        // Next day arrival
-                                                        x = x.Replace("+1", "");
-                                                        TEMP_FlightNextDays = 1;
-                                                        TEMP_FlightNextDayArrival = true;
-                                                    }
-                                                    if (x.Contains("+2"))
-                                                    {
-                                                        // Next day arrival
-                                                        x = x.Replace("+2", "");
-                                                        TEMP_FlightNextDays = 2;
-                                                        TEMP_FlightNextDayArrival = true;
-                                                    }
-                                                    if (x.Contains("+-1"))
-                                                    {
-                                                        // Next day arrival
-                                                        x = x.Replace("+-1", "");
-                                                        TEMP_FlightNextDays = -1;
-                                                        TEMP_FlightNextDayArrival = true;
-                                                    }
-                                                    //DateTime.TryParse(x.Trim(), out TEMP_ArrivalTime);
-                                                    TEMP_ArrivalTime = DateTime.ParseExact(x, "h:mmt", ci);
+                                                    // Next day arrival
+                                                    x = x.Replace("+2", "");
+                                                    TEMP_FlightNextDays = 2;
+                                                    TEMP_FlightNextDayArrival = true;
                                                 }
-                                            }
-                                        //}
-                                        //else
-                                        //{
-                                        //    if (TEMP_DepartTime == DateTime.MinValue)
-                                        //    {
-                                        //        temp_string = temp_string.ToUpper();
-                                        //        TEMP_DepartTime = DateTime.ParseExact(temp_string.Trim(), "h:mmt", ci);
-                                        //    }
-                                        //    else
-                                        //    {
-                                        //        // There is a from value so this is to.
-                                        //        string x = temp_string;
-                                        //        if (x.Contains("+1"))
-                                        //        {
-                                        //            // Next day arrival
-                                        //            x = x.Replace("+1", "");
-                                        //            TEMP_FlightNextDays = 1;
-                                        //            TEMP_FlightNextDayArrival = true;
-                                        //        }
-                                        //        if (x.Contains("+2"))
-                                        //        {
-                                        //            // Next day arrival
-                                        //            x = x.Replace("+2", "");
-                                        //            TEMP_FlightNextDays = 2;
-                                        //            TEMP_FlightNextDayArrival = true;
-                                        //        }
-                                        //        if (x.Contains("+-1"))
-                                        //        {
-                                        //            // Next day arrival
-                                        //            x = x.Replace("+-1", "");
-                                        //            TEMP_FlightNextDays = -1;
-                                        //            TEMP_FlightNextDayArrival = true;
-                                        //        }
-                                        //        x = x.ToUpper();
-                                        //        x = x.Trim();
-                                        //        TEMP_ArrivalTime = DateTime.ParseExact(x, "h:mmt", ci);
-                                        //    }
-                                        //}
+                                                if (x.Contains("+-1"))
+                                                {
+                                                    // Next day arrival
+                                                    x = x.Replace("+-1", "");
+                                                    TEMP_FlightNextDays = -1;
+                                                    TEMP_FlightNextDayArrival = true;
+                                                }
+                                                //DateTime.TryParse(x.Trim(), out TEMP_ArrivalTime);
+                                                TEMP_ArrivalTime = DateTime.ParseExact(x, "h:mmt", ci);
+                                            }
+                                        }
                                     }
                                     // FlightNumber Parsing
                                     if (rgxFlightNumber.IsMatch(temp_string) && TEMP_ArrivalTime != DateTime.MinValue && TEMP_FlightMonday == false && TEMP_FlightTuesday == false && TEMP_FlightWednesday == false && TEMP_FlightThursday == false && TEMP_FlightFriday == false && TEMP_FlightSaterday == false && TEMP_FlightSunday == false)
@@ -322,7 +266,7 @@
                                             if (temp_string.Contains("*"))
                                             {
                                                 TEMP_FlightCodeShare = true;
-                                                TEMP_FlightNumber = TEMP_FlightNumber.Replace("*", "");
+                                                TEMP_FlightNumber = TEMP_FlightNumber.Replace("*", "");
                                             }
                                         }
                                     }
@@ -333,13 +277,13 @@
                                         if (temp_string.Contains("Daily"))
                                         {
                                             // all days
-                                            TEMP_FlightSunday = true;
-                                            TEMP_FlightMonday = true;
-                                            TEMP_FlightTuesday = true;
-                                            TEMP_FlightWednesday = true;
-                                            TEMP_FlightThursday = true;
-                                            TEMP_FlightFriday = true;
-                                            TEMP_FlightSaterday = true;
+                                            TEMP_FlightSunday = true;
+                                            TEMP_FlightMonday = true;
+                                            TEMP_FlightTuesday = true;
+                                            TEMP_FlightWednesday = true;
+                                            TEMP_FlightThursday = true;
+                                            TEMP_FlightFriday = true;
+                                            TEMP_FlightSaterday = true;
                                         }
                                         else
                                         {
@@ -365,7 +309,8 @@
                                                     if (TEMP_Conversie == 7) { TEMP_FlightSunday = false; }
                                                 }
                                             }
-                                            else {
+                                            else
+                                            {
                                                 foreach (Match ItemMatch in rgxFlightDay.Matches(temp_string))
                                                 {
                                                     int.TryParse(ItemMatch.Value, out TEMP_Conversie);
@@ -379,7 +324,7 @@
                                                 }
                                             }
                                         }
-                                    }
+                                    }
                                     //// Aircraft parsing

                                     //if (temp_string.Length == 3)
@@ -428,7 +373,7 @@
                                             FlightSunday = TEMP_FlightSunday,
                                             FlightNumber = TEMP_FlightNumber,
                                             FlightOperator = null,
-                                            FlightDuration = TEMP_DurationTime.ToString(),
+                                            FlightDuration = null,
                                             FlightCodeShare = TEMP_FlightCodeShare,
                                             FlightNextDayArrival = TEMP_FlightNextDayArrival,
                                             FlightNextDays = TEMP_FlightNextDays,
@@ -436,7 +381,7 @@
                                         });
                                         // Cleaning All but From and To
                                         TEMP_ValidFrom = ValidFrom;
-                                        TEMP_ValidTo = new DateTime();
+                                        TEMP_ValidTo = ValidTo;
                                         TEMP_Conversie = 0;
                                         TEMP_FlightMonday = false;
                                         TEMP_FlightTuesday = false;
@@ -454,9 +399,9 @@
                                         TEMP_FlightNextDayArrival = false;
                                         TEMP_FlightNextDays = 0;
                                         TEMP_FlightDirect = true;
-
+
                                     }
-
+
                                     //if (TEMP_Aircraftcode != null && rgxFlightTime.Matches(temp_string).Count > 0)
                                     //{
                                     //    // Aircraft code has been found so this has to be the flighttimes. and so the last value of the string...
@@ -472,7 +417,7 @@
                                     //    if (TEMP_Aircraftcode == "BUS") { TEMP_Airline = null; }
                                     //    else { TEMP_Airline = TEMP_FlightNumber.Substring(0, 2); }

-
+
                                     //}
                                     if (temp_string.Contains("EFF ") || temp_string.Contains("DIS "))
                                     {
@@ -482,7 +427,7 @@
                                             temp_string = temp_string.Replace("EFF ", "");
                                             //TEMP_ValidFrom = DateTime.ParseExact(temp_string.Trim(), "MM/dd/YY", ci);
                                             CIFLights[CIFLights.Count - 1].FromDate = DateTime.ParseExact(temp_string.Trim(), "MM/dd/yy", ci);
-
+
                                         }

                                         if (temp_string.Contains("DIS "))
@@ -521,7 +466,7 @@
                                     //    TEMP_FlightNextDayArrival = false;
                                     //    TEMP_FlightNextDays = 0;
                                     //    TEMP_FlightDirect = true;
-
+
                                     //}
                                     Console.WriteLine(value);
                                 }
@@ -547,59 +492,64 @@
             file.Close();

             //Console.ReadKey();
-            //Console.WriteLine("Insert into Database...");
-            //for (int i = 0; i < CIFLights.Count; i++) // Loop through List with for)
-            //{
-            //    using (SqlConnection connection = new SqlConnection("Server=(local);Database=CI-Import;Trusted_Connection=True;"))
-            //    {
-            //        using (SqlCommand command = new SqlCommand())
-            //        {
-            //            command.Connection = connection;            // <== lacking
-            //            command.CommandType = CommandType.StoredProcedure;
-            //            command.CommandText = "InsertFlight";
-            //            command.Parameters.Add(new SqlParameter("@FlightSource", "SkyTeam"));
-            //            command.Parameters.Add(new SqlParameter("@FromIATA", CIFLights[i].FromIATA));
-            //            command.Parameters.Add(new SqlParameter("@ToIATA", CIFLights[i].ToIATA));
-            //            command.Parameters.Add(new SqlParameter("@FromDate", CIFLights[i].FromDate));
-            //            command.Parameters.Add(new SqlParameter("@ToDate", CIFLights[i].ToDate));
-            //            command.Parameters.Add(new SqlParameter("@FlightMonday", CIFLights[i].FlightMonday));
-            //            command.Parameters.Add(new SqlParameter("@FlightTuesday", CIFLights[i].FlightTuesday));
-            //            command.Parameters.Add(new SqlParameter("@FlightWednesday", CIFLights[i].FlightWednesday));
-            //            command.Parameters.Add(new SqlParameter("@FlightThursday", CIFLights[i].FlightThursday));
-            //            command.Parameters.Add(new SqlParameter("@FlightFriday", CIFLights[i].FlightFriday));
-            //            command.Parameters.Add(new SqlParameter("@FlightSaterday", CIFLights[i].FlightSaterday));
-            //            command.Parameters.Add(new SqlParameter("@FlightSunday", CIFLights[i].FlightSunday));
-            //            command.Parameters.Add(new SqlParameter("@DepartTime", CIFLights[i].DepartTime));
-            //            command.Parameters.Add(new SqlParameter("@ArrivalTime", CIFLights[i].ArrivalTime));
-            //            command.Parameters.Add(new SqlParameter("@FlightNumber", CIFLights[i].FlightNumber));
-            //            command.Parameters.Add(new SqlParameter("@FlightAirline", CIFLights[i].FlightAirline));
-            //            command.Parameters.Add(new SqlParameter("@FlightOperator", CIFLights[i].FlightOperator));
-            //            command.Parameters.Add(new SqlParameter("@FlightAircraft", CIFLights[i].FlightAircraft));
-            //            command.Parameters.Add(new SqlParameter("@FlightCodeShare", CIFLights[i].FlightCodeShare));
-            //            command.Parameters.Add(new SqlParameter("@FlightNextDayArrival", CIFLights[i].FlightNextDayArrival));
-            //            command.Parameters.Add(new SqlParameter("@FlightDuration", CIFLights[i].FlightDuration));
-            //            command.Parameters.Add(new SqlParameter("@FlightNextDays", CIFLights[i].FlightNextDays));
-            //            foreach (SqlParameter parameter in command.Parameters)
-            //            {
-            //                if (parameter.Value == null)
-            //                {
-            //                    parameter.Value = DBNull.Value;
-            //                }
-            //            }
-
-
-            //            try
-            //            {
-            //                connection.Open();
-            //                int recordsAffected = command.ExecuteNonQuery();
-            //            }
-
-            //            finally
-            //            {
-            //                connection.Close();
-            //            }
-            //        }
-            //    }
+            Console.WriteLine("Insert into Database...");
+            for (int i = 0; i < CIFLights.Count; i++) // Loop through List with for)
+            {
+                using (SqlConnection connection = new SqlConnection("Server=(local);Database=CI-Import;Trusted_Connection=True;"))
+                {
+                    using (SqlCommand command = new SqlCommand())
+                    {
+                        command.Connection = connection;            // <== lacking
+                        command.CommandType = CommandType.StoredProcedure;
+                        command.CommandText = "InsertFlight";
+                        command.Parameters.Add(new SqlParameter("@FlightSource", 5));
+                        command.Parameters.Add(new SqlParameter("@FromIATA", CIFLights[i].FromIATA));
+                        command.Parameters.Add(new SqlParameter("@ToIATA", CIFLights[i].ToIATA));
+                        command.Parameters.Add(new SqlParameter("@FromDate", CIFLights[i].FromDate));
+                        command.Parameters.Add(new SqlParameter("@ToDate", CIFLights[i].ToDate));
+                        command.Parameters.Add(new SqlParameter("@FlightMonday", CIFLights[i].FlightMonday));
+                        command.Parameters.Add(new SqlParameter("@FlightTuesday", CIFLights[i].FlightTuesday));
+                        command.Parameters.Add(new SqlParameter("@FlightWednesday", CIFLights[i].FlightWednesday));
+                        command.Parameters.Add(new SqlParameter("@FlightThursday", CIFLights[i].FlightThursday));
+                        command.Parameters.Add(new SqlParameter("@FlightFriday", CIFLights[i].FlightFriday));
+                        command.Parameters.Add(new SqlParameter("@FlightSaterday", CIFLights[i].FlightSaterday));
+                        command.Parameters.Add(new SqlParameter("@FlightSunday", CIFLights[i].FlightSunday));
+                        command.Parameters.Add(new SqlParameter("@DepartTime", CIFLights[i].DepartTime));
+                        command.Parameters.Add(new SqlParameter("@ArrivalTime", CIFLights[i].ArrivalTime));
+                        command.Parameters.Add(new SqlParameter("@FlightNumber", CIFLights[i].FlightNumber));
+                        command.Parameters.Add(new SqlParameter("@FlightAirline", CIFLights[i].FlightAirline));
+                        command.Parameters.Add(new SqlParameter("@FlightOperator", CIFLights[i].FlightOperator));
+                        command.Parameters.Add(new SqlParameter("@FlightAircraft", CIFLights[i].FlightAircraft));
+                        command.Parameters.Add(new SqlParameter("@FlightCodeShare", CIFLights[i].FlightCodeShare));
+                        command.Parameters.Add(new SqlParameter("@FlightNextDayArrival", CIFLights[i].FlightNextDayArrival));
+                        command.Parameters.Add(new SqlParameter("@FlightDuration", CIFLights[i].FlightDuration));
+                        command.Parameters.Add(new SqlParameter("@FlightNextDays", CIFLights[i].FlightNextDays));
+                        command.Parameters.Add(new SqlParameter("@FlightNonStop", "True"));
+                        command.Parameters.Add(new SqlParameter("@FlightVia", DBNull.Value));
+
+
+                        foreach (SqlParameter parameter in command.Parameters)
+                        {
+                            if (parameter.Value == null)
+                            {
+                                parameter.Value = DBNull.Value;
+                            }
+                        }
+
+
+                        try
+                        {
+                            connection.Open();
+                            int recordsAffected = command.ExecuteNonQuery();
+                        }
+
+                        finally
+                        {
+                            connection.Close();
+                        }
+                    }
+                }
+            }
         }

     }


ProjectUtility: multi user conflict added

--- Suplanus.Sepla/Helper/ProjectUtility.cs
+++ Suplanus.Sepla/Helper/ProjectUtility.cs
@@ -1,6 +1,8 @@
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using System.Text;
+using System.Windows;
 using Eplan.EplApi.DataModel;
 using Eplan.EplApi.DataModel.MasterData;
 using Eplan.EplApi.HEServices;
@@ -183,6 +185,50 @@
          }
       }

+      /// <summary>
+      /// Returns true if there is a multi user conflict in project
+      /// </summary>
+      /// <param name="project">EPLAN project</param>
+      /// <param name="showDialog">Shows dialog if there is a conflict (optional)</param>
+      /// <returns></returns>
+      public static bool IsMultiUserConflict(Project project, bool showDialog = false)
+      {
+         var currentUsers = project.CurrentUsers.ToList();
+
+         // No conflict
+         if (currentUsers.Count <= 1)
+         {
+            return false;
+         }
+
+         // Conflict
+         if (showDialog)
+         {
+            StringBuilder sb = new StringBuilder();
+            sb.AppendLine("Multi user conflict:");
+            foreach (var user in currentUsers)
+            {
+               if (!string.IsNullOrEmpty(user.Name) && !string.IsNullOrEmpty(user.Identification))
+               {
+                  sb.AppendLine(user.ComputerName + " / " + user.Name + " / " + user.Identification);
+               }
+               else if (!string.IsNullOrEmpty(user.Name))
+               {
+                  sb.AppendLine(user.ComputerName + " / " + user.Name);
+               }
+               else if (!string.IsNullOrEmpty(user.Identification))
+               {
+                  sb.AppendLine(user.ComputerName + " / " + user.Identification);
+               }
+               else
+               {
+                  sb.AppendLine(user.ComputerName);
+               }
+            }
+            MessageBox.Show(sb.ToString(), "Multi user conflict", MessageBoxButton.OK, MessageBoxImage.Warning);
+         }
+         return true;
+      }

    }
 }


implemented method to set color

implemented method to set color

--- src/biz.dfch.CS.Osram.Lightify.Client/ClientGroupOperation.cs
+++ src/biz.dfch.CS.Osram.Lightify.Client/ClientGroupOperation.cs
@@ -204,7 +204,7 @@

         public bool SetGroupColor(long groupId, string hexColor)
         {
-            return false;
+            return SetGroupColor(groupId, hexColor, 0);
         }

         public bool SetGroupColor(Group group, string hexColor, long time)
@@ -214,7 +214,23 @@

         public bool SetGroupColor(long groupId, string hexColor, long time)
         {
-            return false;
+            Contract.Requires(0 < groupId);
+            if (hexColor.Contains("#"))
+            {
+                hexColor = hexColor.Replace("#", "");
+            }
+            Contract.Assert(hexColor.All("0123456789abcdefABCDEF".Contains));
+            Contract.Assert(hexColor.Length == 6);
+
+            var queryParams = new Dictionary<string, object>
+            {
+                {Constants.QueryParameter.IDX, groupId},
+                {Constants.QueryParameter.COLOR, hexColor},
+                {Constants.QueryParameter.TIME, time}
+            };
+
+            var result = Invoke<OperationResponse>(HttpMethod.Get, Constants.ApiOperation.GROUP_SET, queryParams, null, null);
+            return result.ReturnCode == 0;
         }
     }
 }


Add more Menu examples

Add more Menu examples

includes CheckBox, RadioButton and a SubMenu

--- TestApps/Samples/Samples/MenuSamples.cs
+++ TestApps/Samples/Samples/MenuSamples.cs
@@ -40,7 +40,29 @@
 			menu.Items.Add (new MenuItem ("Two"));
 			menu.Items.Add (new MenuItem ("Three"));
 			menu.Items.Add (new SeparatorMenuItem ());
-			menu.Items.Add (new MenuItem ("End"));
+
+			var rgroup = new RadioButtonMenuItemGroup ();
+			menu.Items.Add (new RadioButtonMenuItem ("Opt 1") { Group = rgroup, Sensitive = false });
+			menu.Items.Add (new RadioButtonMenuItem ("Opt 2") { Group = rgroup, Checked = true });
+			menu.Items.Add (new RadioButtonMenuItem ("Opt 3") { Group = rgroup });
+
+			menu.Items.Add (new SeparatorMenuItem ());
+
+			menu.Items.Add (new CheckBoxMenuItem ("Check 1"));
+			menu.Items.Add (new CheckBoxMenuItem ("Check 2") { Checked = true });
+
+			menu.Items.Add (new SeparatorMenuItem ());
+
+			var subMenu = new MenuItem ("Submenu");
+			subMenu.SubMenu = new Menu ();
+			var subZoomIn = new MenuItem (new Command ("Zoom+", StockIcons.ZoomIn));
+			var subZoomOut = new MenuItem (new Command ("Zoom-", StockIcons.ZoomOut));
+			subMenu.SubMenu.Items.Add (subZoomIn);
+			subMenu.SubMenu.Items.Add (subZoomOut);
+			menu.Items.Add (subMenu);
+
+			subZoomIn.Clicked += (sender, e) => MessageDialog.ShowMessage ("'Zoom+' item clicked.");
+			subZoomOut.Clicked += (sender, e) => MessageDialog.ShowMessage ("'Zoom-' item clicked.");

 			la.ButtonPressed += HandleButtonPressed;
 			PackStart (la);


BUGGED another attempt

BUGGED another attempt

--- Bend/LayerManager/RootMetadata/RangemapManager.cs
+++ Bend/LayerManager/RootMetadata/RangemapManager.cs
@@ -1193,36 +1193,31 @@
                                 // this entry was tombstoned.
                                 continue;
                             }
-                            if (segmentsWithRecords_ByGeneration[i].Key != null &&
-                                  segmentsWithRecords_ByGeneration[i].Key.CompareTo(rk) > 0) {
-                                // We also consider it tombstoned if
-                                // it's in "segmentsWithRecords" before us, because that means there was
-                                // another value of the exact same segment key above us, which could
-                                // have hidden our tombstone in it's shadow.
-                                break; // and it also means we can stop now
-                            }
-
-                            if (direction_is_forward) {
+
+                            if (!direction_is_forward) {
+                                // we're headed in the direction of this scan, so get the next valid segment
+                                // so long as it appears sooner than the one we have already
+                                var segment = this.segmentReaderFromRow(nextrec);
+                                segmentsWithRecords.Add(rk, segment);
+                                if (segmentsWithRecords_ByGeneration[i].Key == null ||
+                                        segmentsWithRecords_ByGeneration[i].Key.CompareTo(rk) < 0) {
+                                    segmentsWithRecords_ByGeneration[i] =
+                                            new KeyValuePair<RangeKey, IScannable<RecordKey, RecordUpdate>>(rk, segment);
+                                }
+                                break;
+                            } else {
+                                // we're headed in the opposite direction of the scan, so only grab a
+                                // segment if we're inside it _and_ not inside our current candidate
                                 int cmpval = startkeytest.CompareTo(rk.highkey);
                                 if ((cmpval < 0) || (cmpval == 0 && equal_ok)) {
                                     var segment = this.segmentReaderFromRow(nextrec);
                                     segmentsWithRecords.Add(rk, segment);
                                     if (segmentsWithRecords_ByGeneration[i].Key == null ||
-                                        segmentsWithRecords_ByGeneration[i].Key.CompareTo(rk) > 0) {
+                                        startkeytest.CompareTo(segmentsWithRecords_ByGeneration[i].Key.highkey) < 0) {
                                         segmentsWithRecords_ByGeneration[i] =
                                             new KeyValuePair<RangeKey, IScannable<RecordKey, RecordUpdate>>(rk, segment);
                                     }
-
-                                }
-                            } else {
-                                // really only need this if below doesn't find one?
-                                var segment = this.segmentReaderFromRow(nextrec);
-                                segmentsWithRecords.Add(rk, segment);
-                                if (segmentsWithRecords_ByGeneration[i].Key == null ||
-                                        segmentsWithRecords_ByGeneration[i].Key.CompareTo(rk) > 0) {
-
-                                    segmentsWithRecords_ByGeneration[i] =
-                                            new KeyValuePair<RangeKey, IScannable<RecordKey, RecordUpdate>>(rk, segment);
+
                                 }

                             }
@@ -1253,38 +1248,30 @@
                                 // this entry was tombstoned.
                                 continue;
                             }
-                            if (segmentsWithRecords_ByGeneration[i].Key != null &&
-                                 segmentsWithRecords_ByGeneration[i].Key.CompareTo(rk) < 0) {
-                                // We also consider it tombstoned if
-                                // it's in "segmentsWithRecords" before us, because that means there was
-                                // another value of the exact same segment key above us, which could
-                                // have hidden our tombstone in it's shadow.
-                                break;  // and it also means we can stop now
-                            }
-
-                            if (!direction_is_forward) {
+
+                            if (direction_is_forward) {
+                                // we're headed in the direction of this scan, so get the next valid segment
+                                // so long as it appears sooner than the one we have already
+                                var segment = this.segmentReaderFromRow(nextrec);
+                                segmentsWithRecords.Add(rk, segment);
+
+                                if (segmentsWithRecords_ByGeneration[i].Key == null ||
+                                        segmentsWithRecords_ByGeneration[i].Key.CompareTo(rk) > 0) {
+                                        segmentsWithRecords_ByGeneration[i] =
+                                                new KeyValuePair<RangeKey, IScannable<RecordKey, RecordUpdate>>(rk, segment);
+                                }
+                            } else {
+                                // we're headed in the opposite direction of the scan, so only grab a
+                                // segment if we're inside it _and_ not inside our current candidate
                                 int cmpval = startkeytest.CompareTo(rk.lowkey);
                                 if ((cmpval > 0) || (cmpval == 0 && equal_ok)) {
                                     var segment = this.segmentReaderFromRow(nextrec);
                                     segmentsWithRecords.Add(rk, segment);

                                     if (segmentsWithRecords_ByGeneration[i].Key == null ||
-                                        segmentsWithRecords_ByGeneration[i].Key.CompareTo(rk) < 0) {
+                                        startkeytest.CompareTo(segmentsWithRecords_ByGeneration[i].Key.lowkey) > 0) {
                                         segmentsWithRecords_ByGeneration[i] =
                                             new KeyValuePair<RangeKey, IScannable<RecordKey, RecordUpdate>>(rk, segment);
-                                    }
-                                }
-                            } else {
-                                if (segmentsWithRecords_ByGeneration[i].Key == null ||
-                                        segmentsWithRecords_ByGeneration[i].Key.CompareTo(rk) > 0) {
-
-                                    var segment = this.segmentReaderFromRow(nextrec);
-                                    segmentsWithRecords.Add(rk, segment);
-
-                                    if (segmentsWithRecords_ByGeneration[i].Key == null ||
-                                        segmentsWithRecords_ByGeneration[i].Key.CompareTo(rk) > 0) {
-                                        segmentsWithRecords_ByGeneration[i] =
-                                                new KeyValuePair<RangeKey, IScannable<RecordKey, RecordUpdate>>(rk, segment);
                                     }
                                 }


Fix to avoid SA1516

Fix to avoid SA1516

--- ThScoreFileConverter/Models/Squirrel.cs
+++ ThScoreFileConverter/Models/Squirrel.cs
@@ -18,38 +18,55 @@

         public const SQObjectType OTNull =
             SQObjectType.RTNull | SQObjectType.SQObjectCanBeFalse;
+
         public const SQObjectType OTInteger =
             SQObjectType.RTInteger | SQObjectType.SQObjectNumeric | SQObjectType.SQObjectCanBeFalse;
+
         public const SQObjectType OTFloat =
             SQObjectType.RTFloat | SQObjectType.SQObjectNumeric | SQObjectType.SQObjectCanBeFalse;
+
         public const SQObjectType OTBool =
             SQObjectType.RTBool | SQObjectType.SQObjectCanBeFalse;
+
         public const SQObjectType OTString =
             SQObjectType.RTString | SQObjectType.SQObjectRefCounted;
+
         public const SQObjectType OTTable =
             SQObjectType.RTTable | SQObjectType.SQObjectRefCounted | SQObjectType.SQObjectDelegable;
+
         public const SQObjectType OTArray =
             SQObjectType.RTArray | SQObjectType.SQObjectRefCounted;
+
         public const SQObjectType OTUserData =
             SQObjectType.RTUserData | SQObjectType.SQObjectRefCounted | SQObjectType.SQObjectDelegable;
+
         public const SQObjectType OTClosure =
             SQObjectType.RTClosure | SQObjectType.SQObjectRefCounted;
+
         public const SQObjectType OTNativeClosure =
             SQObjectType.RTNativeClosure | SQObjectType.SQObjectRefCounted;
+
         public const SQObjectType OTGenerator =
             SQObjectType.RTGenerator | SQObjectType.SQObjectRefCounted;
+
         public const SQObjectType OTUserPointer =
             SQObjectType.RTUserPointer;
+
         public const SQObjectType OTThread =
             SQObjectType.RTThread | SQObjectType.SQObjectRefCounted;
+
         public const SQObjectType OTFuncProto =
             SQObjectType.RTFuncProto | SQObjectType.SQObjectRefCounted;
+
         public const SQObjectType OTClass =
             SQObjectType.RTClass | SQObjectType.SQObjectRefCounted;
+
         public const SQObjectType OTInstance =
             SQObjectType.RTInstance | SQObjectType.SQObjectRefCounted | SQObjectType.SQObjectDelegable;
+
         public const SQObjectType OTWeakRef =
             SQObjectType.RTWeakRef | SQObjectType.SQObjectRefCounted;
+
         public const SQObjectType OTOuter =
             SQObjectType.RTOuter | SQObjectType.SQObjectRefCounted;


handled concurrency issue on init

handled concurrency issue on init

--- TheWheel.ServiceBus/ServiceBusClient.cs
+++ TheWheel.ServiceBus/ServiceBusClient.cs
@@ -49,41 +49,44 @@
         public void EnsureBrokerReady()
         {
             EnsureConnectionIsOpen();
-            var cmd = connection.CreateCommand();
-            // Message type
-            cmd.CommandText = "SELECT Count(1) FROM sys.service_message_types WHERE name='" + MessageType + "'";
-            if (Convert.ToInt32(cmd.ExecuteScalar()) == 0)
-            {
+            lock (connection)
+            {
+                var cmd = connection.CreateCommand();
+                // Message type
+                cmd.CommandText = "SELECT Count(1) FROM sys.service_message_types WHERE name='" + MessageType + "'";
+                if (Convert.ToInt32(cmd.ExecuteScalar()) == 0)
+                {
+                    cmd = connection.CreateCommand();
+                    cmd.CommandText = "CREATE MESSAGE TYPE [" + MessageType + "] VALIDATION = NONE";
+                    cmd.ExecuteNonQuery();
+                }
+                // contracts
                 cmd = connection.CreateCommand();
-                cmd.CommandText = "CREATE MESSAGE TYPE [" + MessageType + "] VALIDATION = NONE";
-                cmd.ExecuteNonQuery();
-            }
-            // contracts
-            cmd = connection.CreateCommand();
-            cmd.CommandText = "SELECT Count(1) FROM sys.service_contracts WHERE name='" + Contract + "'";
-            if (Convert.ToInt32(cmd.ExecuteScalar()) == 0)
-            {
+                cmd.CommandText = "SELECT Count(1) FROM sys.service_contracts WHERE name='" + Contract + "'";
+                if (Convert.ToInt32(cmd.ExecuteScalar()) == 0)
+                {
+                    cmd = connection.CreateCommand();
+                    cmd.CommandText = "CREATE CONTRACT [" + Contract + "] ([" + MessageType + "] SENT BY ANY)";
+                    cmd.ExecuteNonQuery();
+                }
+                // queues
                 cmd = connection.CreateCommand();
-                cmd.CommandText = "CREATE CONTRACT [" + Contract + "] ([" + MessageType + "] SENT BY ANY)";
-                cmd.ExecuteNonQuery();
-            }
-            // queues
-            cmd = connection.CreateCommand();
-            cmd.CommandText = "SELECT Count(1) FROM sys.service_queues WHERE name='" + Queue + "'";
-            if (Convert.ToInt32(cmd.ExecuteScalar()) == 0)
-            {
+                cmd.CommandText = "SELECT Count(1) FROM sys.service_queues WHERE name='" + Queue + "'";
+                if (Convert.ToInt32(cmd.ExecuteScalar()) == 0)
+                {
+                    cmd = connection.CreateCommand();
+                    cmd.CommandText = "CREATE QUEUE [" + Queue + "]";
+                    cmd.ExecuteNonQuery();
+                }
+                // services
                 cmd = connection.CreateCommand();
-                cmd.CommandText = "CREATE QUEUE [" + Queue + "]";
-                cmd.ExecuteNonQuery();
-            }
-            // services
-            cmd = connection.CreateCommand();
-            cmd.CommandText = "SELECT Count(1) FROM sys.services WHERE name='" + Service + "'";
-            if (Convert.ToInt32(cmd.ExecuteScalar()) == 0)
-            {
-                cmd = connection.CreateCommand();
-                cmd.CommandText = "CREATE SERVICE [" + Service + "] ON QUEUE [" + Queue + "] ([" + Contract + "])";
-                cmd.ExecuteNonQuery();
+                cmd.CommandText = "SELECT Count(1) FROM sys.services WHERE name='" + Service + "'";
+                if (Convert.ToInt32(cmd.ExecuteScalar()) == 0)
+                {
+                    cmd = connection.CreateCommand();
+                    cmd.CommandText = "CREATE SERVICE [" + Service + "] ON QUEUE [" + Queue + "] ([" + Contract + "])";
+                    cmd.ExecuteNonQuery();
+                }
             }
         }

@@ -107,23 +110,25 @@

         private IEnumerable<TMessage> GetMessages(IDbCommand cmd)
         {
-
             ICollection<TMessage> messages = new List<TMessage>();
-            using (var reader = cmd.ExecuteReader())
-            {
-                while (reader.Read())
-                {
-                    if (reader.FieldCount < 3)
-                        continue;
-                    var type = reader.GetString(2);
-                    var handle = reader.GetGuid(1);
-                    if (type == MessageType)
+            lock (connection)
+            {
+                using (var reader = cmd.ExecuteReader())
+                {
+                    while (reader.Read())
                     {
-                        var m = JsonConvert.DeserializeObject<TMessage>(reader.GetString(0));
-                        m.ConversationHandle = handle;
-                        //m.ConversationGroup = reader.GetGuid(3);
-                        Init(m);
-                        messages.Add(m);
+                        if (reader.FieldCount < 3)
+                            continue;
+                        var type = reader.GetString(2);
+                        var handle = reader.GetGuid(1);
+                        if (type == MessageType)
+                        {
+                            var m = JsonConvert.DeserializeObject<TMessage>(reader.GetString(0));
+                            m.ConversationHandle = handle;
+                            //m.ConversationGroup = reader.GetGuid(3);
+                            Init(m);
+                            messages.Add(m);
+                        }
                     }
                 }
             }


Improve performance of Batch (about 5x faster)

--- src/Linq.Extras/Batch.cs
+++ src/Linq.Extras/Batch.cs
@@ -1,5 +1,4 @@
 using System.Collections.Generic;
-using System.Linq;
 using JetBrains.Annotations;
 using Linq.Extras.Internal;

@@ -22,10 +21,26 @@
             source.CheckArgumentNull(nameof(source));
             size.CheckArgumentOutOfRange(nameof(size), 1, int.MaxValue);

-            return source
-                .WithIndex()
-                .GroupBy(x => x.Index / size)
-                .Select(g => g.WithoutIndex());
+            return BatchImpl(source, size);
+
+            static IEnumerable<IEnumerable<TSource>> BatchImpl(IEnumerable<TSource> source, int size)
+            {
+                var batch = new List<TSource>();
+                foreach (var item in source)
+                {
+                    batch.Add(item);
+                    if (batch.Count == size)
+                    {
+                        yield return batch;
+                        batch = new List<TSource>();
+                    }
+                }
+
+                if (batch.Count > 0)
+                {
+                    yield return batch;
+                }
+            }
         }
     }
 }


Bumped version to 0.9.3.0

Bumped version to 0.9.3.0

--- BitcoinTransactionTool/Properties/AssemblyInfo.cs
+++ BitcoinTransactionTool/Properties/AssemblyInfo.cs
@@ -10,9 +10,9 @@
 [assembly: AssemblyTitle("BitcoinTransactionTool")]
 [assembly: AssemblyDescription("")]
 [assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyCompany("Coding Enthusiast")]
 [assembly: AssemblyProduct("BitcoinTransactionTool")]
-[assembly: AssemblyCopyright("Copyright © Microsoft 2016")]
+[assembly: AssemblyCopyright("Copyright © Coding Enthusiast 2017")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]

@@ -51,5 +51,5 @@
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.9.2.0")]
-[assembly: AssemblyFileVersion("0.9.2.0")]
+[assembly: AssemblyVersion("0.9.3.0")]
+[assembly: AssemblyFileVersion("0.9.3.0")]


Added Log action

Added Log action

--- src/Modules/Tools/Log.cs
+++ src/Modules/Tools/Log.cs
@@ -1,15 +1,25 @@
 using System;
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
 using System.Text;
+using LightningDevelopment;

 namespace Tools.Tools
 {
-    public class Log : ITool
+    public class Log : IQuickAction
     {
+        public string Command
+        {
+            get { return "log"; }
+        }
+
         public void Execute()
         {
-            TortoiseProc.Do(TortoiseProc.Command.Log, Config.TheWizardsRoot);
+            if (!Directory.Exists(Context.WorkingDir))
+                return;
+            TortoiseProc.Do(TortoiseProc.Command.Log, Context.WorkingDir);
         }
     }
 }
+


OrderedInstallerFactory used

OrderedInstallerFactory used

--- src/NArms.Windsor/IoC.cs
+++ src/NArms.Windsor/IoC.cs
@@ -17,7 +17,8 @@
         /// </summary>
         public static void Init()
         {
-            var installerAssembly = FromAssembly.Instance(Assembly.GetCallingAssembly());
+            var installerAssembly = FromAssembly.Instance(Assembly.GetCallingAssembly(),
+                                                          new OrderedInstallerFactory());
             Init(new WindsorContainer().Install(installerAssembly));
         }


Add helpers to Result.

Add helpers to Result.

--- src/Narvalo.Fx/Result.cs
+++ src/Narvalo.Fx/Result.cs
@@ -4,6 +4,8 @@
 {
     using System;
     using System.Collections.Generic;
+    using System.Diagnostics.CodeAnalysis;
+    using System.Runtime.ExceptionServices;

     /// <summary>
     /// Provides a set of static and extension methods for <see cref="Result{T, TError}"/>
@@ -21,6 +23,104 @@
             if (@this.IsError)
             {
                 throw @this.Error;
+            }
+        }
+
+        public static void ThrowIfError<T>(this Result<T, ExceptionDispatchInfo> @this)
+        {
+            Require.NotNull(@this, nameof(@this));
+
+            if (@this.IsError)
+            {
+                @this.Error.Throw();
+            }
+        }
+
+        // NB: This method serves a different purpose than the trywith from F# workflows.
+        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "[Intentionally] Raison d'être of VoidOrError.")]
+        public static Result<Unit, ExceptionDispatchInfo> TryWith(Action action)
+        {
+            Require.NotNull(action, nameof(action));
+
+            try
+            {
+                action.Invoke();
+
+                return Of<Unit, ExceptionDispatchInfo>(Unit.Default);
+            }
+            catch (Exception ex)
+            {
+                var edi = ExceptionDispatchInfo.Capture(ex);
+
+                return FromError<Unit, ExceptionDispatchInfo>(edi);
+            }
+        }
+
+        // NB: This method is **not** the trywith from F# workflows.
+        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "[Intentionally] Raison d'être of ResultOrError.")]
+        public static Result<TResult, ExceptionDispatchInfo> TryWith<TResult>(Func<TResult> func)
+        {
+            Require.NotNull(func, nameof(func));
+
+            try
+            {
+                return Of<TResult, ExceptionDispatchInfo>(func.Invoke());
+            }
+            catch (Exception ex)
+            {
+                var edi = ExceptionDispatchInfo.Capture(ex);
+
+                return FromError<TResult, ExceptionDispatchInfo>(edi);
+            }
+        }
+
+        // NB: This method serves a different purpose than the tryfinally from F# workflows.
+        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "[Intentionally] Raison d'être of VoidOrError.")]
+        public static Result<Unit, ExceptionDispatchInfo> TryFinally(Action action, Action finallyAction)
+        {
+            Require.NotNull(action, nameof(action));
+            Require.NotNull(finallyAction, nameof(finallyAction));
+
+            try
+            {
+                action.Invoke();
+
+                return Of<Unit, ExceptionDispatchInfo>(Unit.Default);
+            }
+            catch (Exception ex)
+            {
+                var edi = ExceptionDispatchInfo.Capture(ex);
+
+                return FromError<Unit, ExceptionDispatchInfo>(edi);
+            }
+            finally
+            {
+                finallyAction.Invoke();
+            }
+        }
+
+        // NB: This method is **not** the tryfinally from F# workflows.
+        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "[Intentionally] Raison d'être of ResultOrError.")]
+        public static Result<TResult, ExceptionDispatchInfo> TryFinally<TResult>(
+            Func<TResult> func,
+            Action finallyAction)
+        {
+            Require.NotNull(func, nameof(func));
+            Require.NotNull(finallyAction, nameof(finallyAction));
+
+            try
+            {
+                return Of<TResult, ExceptionDispatchInfo>(func.Invoke());
+            }
+            catch (Exception ex)
+            {
+                var edi = ExceptionDispatchInfo.Capture(ex);
+
+                return FromError<TResult, ExceptionDispatchInfo>(edi);
+            }
+            finally
+            {
+                finallyAction.Invoke();
             }
         }
     }


Use FirstOrDefault because own email could be more than once in attendees

--- CalDavSynchronizer/Implementation/EntityMapper.cs
+++ CalDavSynchronizer/Implementation/EntityMapper.cs
@@ -850,7 +850,7 @@

       if (source.Organizer != null)
       {
-        var ownSourceAttendee = source.Attendees.SingleOrDefault (a => StringComparer.InvariantCultureIgnoreCase.Compare (a.Value.ToString(), _serverEmailUri) == 0);
+        var ownSourceAttendee = source.Attendees.FirstOrDefault (a => StringComparer.InvariantCultureIgnoreCase.Compare (a.Value.ToString(), _serverEmailUri) == 0);
         if (ownSourceAttendee != null)
         {
           var response = MapParticipation2ToMeetingResponse (ownSourceAttendee.ParticipationStatus);


removed duplicate check for tel item count.

--- test/FunctionalTestUtils20/TelemetryExtensions.cs
+++ test/FunctionalTestUtils20/TelemetryExtensions.cs
@@ -47,12 +47,7 @@
                 .Take(count)
                 .ToEnumerable()
                 .ToArray();
-
-            if (result.Length < count)
-            {
-                throw new InvalidDataException("Incorrect number of items. Expected: " + count + " Received: " + result.Length);
-            }
-
+
             return result;
         }

@@ -81,7 +76,7 @@
                 .ToEnumerable()
                 .ToArray();

-            if (result.Length < count)
+            if (result.Length != count)
             {
                 throw new InvalidDataException("Incorrect number of items. Expected: " + count + " Received: " + result.Length);
             }


Fix SmartDateExtendedParser #4

Fix SmartDateExtendedParser #4

--- trunk/Source/CslaContrib/SmartDateExtendedParser.cs
+++ trunk/Source/CslaContrib/SmartDateExtendedParser.cs
@@ -1,314 +1,317 @@
-using System;
-using System.Text.RegularExpressions;
-
-namespace CslaContrib
-{
-  /// <summary>
-  /// SmartDate extended parsing for relative dates and short date form parsing.
-  /// </summary>
-  public static class SmartDateExtendedParser
-  {
-    /// <summary>
-    /// Entry point for Csla.SmartDate customized parser.
-    /// </summary>
-    /// <param name="value">The value.</param>
-    /// <returns></returns>
-    public static DateTime? ExtendedParser(string value)
-    {
-      var result = new DateTime();
-      if (TryStringToDate(value, ref result))
-        return result;
-
-      return null;
-    }
-
-    private static bool TryStringToDate(string value, ref DateTime result)
-    {
-      if (String.IsNullOrEmpty(value))
-      {
-        return false;
-      }
-
-      DateTime tmp;
-
-      if (NearestDate(value, out tmp))
-      {
-        result = tmp;
-        return true;
-      }
-
-      var ldate = value.Trim().ToLower();
-      if (ldate == "<")
-      {
-        result = DateTime.Now.AddMonths(-1);
-        return true;
-      }
-      if (ldate == ">")
-      {
-        result = DateTime.Now.AddMonths(1);
-        return true;
-      }
-      if (ldate == "<<")
-      {
-        result = DateTime.Now.AddYears(-1);
-        return true;
-      }
-      if (ldate == ">>")
-      {
-        result = DateTime.Now.AddYears(1);
-        return true;
-      }
-      if (ldate.Substring(0, 1) == "+")
-      {
-        try
-        {
-          result = DateTime.Now.AddDays(Convert.ToInt32(ldate.Substring(1)));
-        }
-        catch (FormatException)
-        {
-          return false;
-        }
-        return true;
-      }
-      if (ldate.Substring(0, 1) == "-")
-      {
-        try
-        {
-          result = DateTime.Now.AddDays(-1*Convert.ToInt32(ldate.Substring(1)));
-        }
-        catch (FormatException)
-        {
-          return false;
-        }
-        return true;
-      }
-      if (ldate.Substring(0, 2) == "<<")
-      {
-        try
-        {
-          result = DateTime.Now.AddYears(-1*Convert.ToInt32(ldate.Substring(2)));
-        }
-        catch (FormatException)
-        {
-          return false;
-        }
-        return true;
-      }
-      if (ldate.Substring(0, 1) == "<")
-      {
-        try
-        {
-          result = DateTime.Now.AddMonths(-1*Convert.ToInt32(ldate.Substring(1)));
-        }
-        catch (FormatException)
-        {
-          return false;
-        }
-        return true;
-      }
-      if (ldate.Substring(0, 2) == ">>")
-      {
-        try
-        {
-          result = DateTime.Now.AddYears(Convert.ToInt32(ldate.Substring(2)));
-        }
-        catch (FormatException)
-        {
-          return false;
-        }
-        return true;
-      }
-      if (ldate.Substring(0, 1) == ">")
-      {
-        try
-        {
-          result = DateTime.Now.AddMonths(Convert.ToInt32(ldate.Substring(1)));
-        }
-        catch (FormatException)
-        {
-          return false;
-        }
-        return true;
-      }
-#if !SILVERLIGHT
-      if (Regex.IsMatch(ldate, @"^\d{1,2}$", RegexOptions.Compiled))
-#else
-      if (Regex.IsMatch(ldate, @"^\d{1,2}$"))
-#endif
-      {
-        int day;
-        try
-        {
-          day = Convert.ToInt32(ldate);
-        }
-        catch (FormatException)
-        {
-          return false;
-        }
-        if (DateTime.Now.Day - day < -16)
-        {
-          return KeepDay(new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddMonths(-1), day, out result);
-        }
-        if (DateTime.Now.Day - day > 16)
-        {
-          return KeepDay(new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddMonths(1), day, out result);
-        }
-        result = new DateTime(DateTime.Now.Year, DateTime.Now.Month, day);
-        return true;
-      }
-
-      value = NormalizeAllShortForms(value.Trim());
-      if (DateTime.TryParse(value, out tmp))
-      {
-        result = tmp;
-        return true;
-      }
-
-      return false;
-    }
-
-    private static string NormalizeAllShortForms(string value)
-    {
-      var pattern = System.Globalization.DateTimeFormatInfo.CurrentInfo.ShortDatePattern;
-#if! SILVERLIGHT
-      var separator = System.Globalization.DateTimeFormatInfo.CurrentInfo.DateSeparator;
-#else
-      var separator = pattern.Replace("y", string.Empty).Replace("d", string.Empty).Replace("M", string.Empty).Substring(0, 1);
-#endif
-
-      // Normalize separator
-#if !SILVERLIGHT
-      value = Regex.Replace(value, @"[ .,/\-\\]", separator, RegexOptions.Compiled);
-#else
-      value = Regex.Replace(value, @"[ .,/\-\\]", separator);
-#endif
-      // Insert missing zeros
-      var valueParts = value.Split(separator.ToCharArray());
-      for (var i = 0; i < valueParts.Length; i++)
-      {
-        if (valueParts[i].Length > 0 && valueParts[i].Length < 2)
-          valueParts[i] = "0" + valueParts[i];
-      }
-
-      // Re-assemble without separator
-      value = string.Join(string.Empty, valueParts);
-
-      var nrDigits = value.Length;
-      var patternElements = pattern.Split(separator.ToCharArray());
-#if !SILVERLIGHT
-      if (Regex.IsMatch(value, @"^\d{4}$", RegexOptions.Compiled) ||
-          Regex.IsMatch(value, @"^\d{6}$", RegexOptions.Compiled) ||
-          Regex.IsMatch(value, @"^\d{8}$", RegexOptions.Compiled))
-#else
-      if (Regex.IsMatch(value, @"^\d{4}$") ||
-          Regex.IsMatch(value, @"^\d{6}$") ||
-          Regex.IsMatch(value, @"^\d{8}$"))
-#endif
-      {
-        var tempValue = string.Empty;
-        var valuePointer = 0;
-
-        foreach (var element in patternElements)
-        {
-          if (element.IndexOf("d", StringComparison.Ordinal) != -1)
-          {
-            tempValue += value.Substring(valuePointer, 2) + separator;
-            valuePointer = valuePointer + 2;
-          }
-          else if (element.IndexOf("M", StringComparison.Ordinal) != -1)
-          {
-            tempValue += value.Substring(valuePointer, 2) + separator;
-            valuePointer = valuePointer + 2;
-          }
-          else if (element.IndexOf("y", StringComparison.Ordinal) != -1)
-          {
-            if (nrDigits == 4)
-            {
-              tempValue += DateTime.Now.Year + separator;
-            }
-            else
-            {
-              tempValue += value.Substring(valuePointer, (nrDigits == 6 ? 2 : 4)) + separator;
-              valuePointer = valuePointer + (nrDigits == 6 ? 2 : 4);
-            }
-          }
-        }
-        value = tempValue.Substring(0, tempValue.Length - 1);
-      }
-
-      return value;
-    }
-
-    private static bool NearestDate(string value, out DateTime result)
-    {
-      result = DateTime.MaxValue;
-
-#if !SILVERLIGHT
-      if (Regex.IsMatch(value, @"^\d{1,2}$", RegexOptions.Compiled))
-#else
-      if (Regex.IsMatch(value, @"^\d{1,2}$"))
-#endif
-      {
-        // Convert day-only to nearest date and return
-        int day;
-        try
-        {
-          day = Convert.ToInt32(value);
-        }
-        catch (FormatException)
-        {
-          return false;
-        }
-
-        if (day > 31)
-          return false;
-
-        DateTime tmp;
-        if (DateTime.Now.Day - day < -16)
-        {
-          if (KeepDay(new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddMonths(-1), day, out tmp))
-          {
-            result = tmp;
-            return true;
-          }
-        }
-        else if (DateTime.Now.Day - day > 16)
-        {
-          if (KeepDay(new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddMonths(1), day, out tmp))
-          {
-            result = tmp;
-            return true;
-          }
-        }
-        else
-        {
-          try
-          {
-            result = new DateTime(DateTime.Now.Year, DateTime.Now.Month, day);
-            return true;
-          }
-          catch (ArgumentOutOfRangeException)
-          {
-            return false;
-          }
-        }
-      }
-
-      return false;
-    }
-
-    private static bool KeepDay(DateTime monthYear, int day, out DateTime result)
-    {
-      try
-      {
-        result = new DateTime(monthYear.Year, monthYear.Month, day);
-        return true;
-      }
-      catch
-      {
-        result = DateTime.MinValue;
-        return false;
-      }
-    }
-  }
-}
+using System;
+using System.Text.RegularExpressions;
+
+namespace CslaContrib
+{
+  /// <summary>
+  /// SmartDate extended parsing for relative dates and short date form parsing.
+  /// </summary>
+  public static class SmartDateExtendedParser
+  {
+    /// <summary>
+    /// Entry point for Csla.SmartDate customized parser.
+    /// </summary>
+    /// <param name="value">The value.</param>
+    /// <returns></returns>
+    public static DateTime? ExtendedParser(string value)
+    {
+      var result = new DateTime();
+      if (TryStringToDate(value, ref result))
+        return result;
+
+      return null;
+    }
+
+    private static bool TryStringToDate(string value, ref DateTime result)
+    {
+      if (String.IsNullOrEmpty(value))
+      {
+        return false;
+      }
+
+      DateTime tmp;
+
+      if (NearestDate(value, out tmp))
+      {
+        result = tmp;
+        return true;
+      }
+
+      var ldate = value.Trim().ToLower();
+      if (ldate == "<")
+      {
+        result = DateTime.Now.AddMonths(-1);
+        return true;
+      }
+      if (ldate == ">")
+      {
+        result = DateTime.Now.AddMonths(1);
+        return true;
+      }
+      if (ldate == "<<")
+      {
+        result = DateTime.Now.AddYears(-1);
+        return true;
+      }
+      if (ldate == ">>")
+      {
+        result = DateTime.Now.AddYears(1);
+        return true;
+      }
+      if (ldate.Substring(0, 1) == "+")
+      {
+        try
+        {
+          result = DateTime.Now.AddDays(Convert.ToInt32(ldate.Substring(1)));
+        }
+        catch (FormatException)
+        {
+          return false;
+        }
+        return true;
+      }
+      if (ldate.Substring(0, 1) == "-")
+      {
+        try
+        {
+          result = DateTime.Now.AddDays(-1*Convert.ToInt32(ldate.Substring(1)));
+        }
+        catch (FormatException)
+        {
+          return false;
+        }
+        return true;
+      }
+      if (ldate.Substring(0, 1) == "<")
+      {
+        try
+        {
+          result = DateTime.Now.AddMonths(-1*Convert.ToInt32(ldate.Substring(1)));
+        }
+        catch (FormatException)
+        {
+          return false;
+        }
+        return true;
+      }
+      if (ldate.Substring(0, 1) == ">")
+      {
+        try
+        {
+          result = DateTime.Now.AddMonths(Convert.ToInt32(ldate.Substring(1)));
+        }
+        catch (FormatException)
+        {
+          return false;
+        }
+        return true;
+      }
+      if (ldate.Length > 1)
+      {
+        if (ldate.Substring(0, 2) == "<<")
+        {
+          try
+          {
+            result = DateTime.Now.AddYears(-1*Convert.ToInt32(ldate.Substring(2)));
+          }
+          catch (FormatException)
+          {
+            return false;
+          }
+          return true;
+        }
+        if (ldate.Substring(0, 2) == ">>")
+        {
+          try
+          {
+            result = DateTime.Now.AddYears(Convert.ToInt32(ldate.Substring(2)));
+          }
+          catch (FormatException)
+          {
+            return false;
+          }
+          return true;
+        }
+      }
+#if !SILVERLIGHT
+      if (Regex.IsMatch(ldate, @"^\d{1,2}$", RegexOptions.Compiled))
+#else
+      if (Regex.IsMatch(ldate, @"^\d{1,2}$"))
+#endif
+      {
+        int day;
+        try
+        {
+          day = Convert.ToInt32(ldate);
+        }
+        catch (FormatException)
+        {
+          return false;
+        }
+        if (DateTime.Now.Day - day < -16)
+        {
+          return KeepDay(new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddMonths(-1), day, out result);
+        }
+        if (DateTime.Now.Day - day > 16)
+        {
+          return KeepDay(new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddMonths(1), day, out result);
+        }
+        result = new DateTime(DateTime.Now.Year, DateTime.Now.Month, day);
+        return true;
+      }
+
+      value = NormalizeAllShortForms(value.Trim());
+      if (DateTime.TryParse(value, out tmp))
+      {
+        result = tmp;
+        return true;
+      }
+
+      return false;
+    }
+
+    private static string NormalizeAllShortForms(string value)
+    {
+      var pattern = System.Globalization.DateTimeFormatInfo.CurrentInfo.ShortDatePattern;
+#if! SILVERLIGHT
+      var separator = System.Globalization.DateTimeFormatInfo.CurrentInfo.DateSeparator;
+#else
+      var separator = pattern.Replace("y", string.Empty).Replace("d", string.Empty).Replace("M", string.Empty).Substring(0, 1);
+#endif
+
+      // Normalize separator
+#if !SILVERLIGHT
+      value = Regex.Replace(value, @"[ .,/\-\\]", separator, RegexOptions.Compiled);
+#else
+      value = Regex.Replace(value, @"[ .,/\-\\]", separator);
+#endif
+      // Insert missing zeros
+      var valueParts = value.Split(separator.ToCharArray());
+      for (var i = 0; i < valueParts.Length; i++)
+      {
+        if (valueParts[i].Length > 0 && valueParts[i].Length < 2)
+          valueParts[i] = "0" + valueParts[i];
+      }
+
+      // Re-assemble without separator
+      value = string.Join(string.Empty, valueParts);
+
+      var nrDigits = value.Length;
+      var patternElements = pattern.Split(separator.ToCharArray());
+#if !SILVERLIGHT
+      if (Regex.IsMatch(value, @"^\d{4}$", RegexOptions.Compiled) ||
+          Regex.IsMatch(value, @"^\d{6}$", RegexOptions.Compiled) ||
+          Regex.IsMatch(value, @"^\d{8}$", RegexOptions.Compiled))
+#else
+      if (Regex.IsMatch(value, @"^\d{4}$") ||
+          Regex.IsMatch(value, @"^\d{6}$") ||
+          Regex.IsMatch(value, @"^\d{8}$"))
+#endif
+      {
+        var tempValue = string.Empty;
+        var valuePointer = 0;
+
+        foreach (var element in patternElements)
+        {
+          if (element.IndexOf("d", StringComparison.Ordinal) != -1)
+          {
+            tempValue += value.Substring(valuePointer, 2) + separator;
+            valuePointer = valuePointer + 2;
+          }
+          else if (element.IndexOf("M", StringComparison.Ordinal) != -1)
+          {
+            tempValue += value.Substring(valuePointer, 2) + separator;
+            valuePointer = valuePointer + 2;
+          }
+          else if (element.IndexOf("y", StringComparison.Ordinal) != -1)
+          {
+            if (nrDigits == 4)
+            {
+              tempValue += DateTime.Now.Year + separator;
+            }
+            else
+            {
+              tempValue += value.Substring(valuePointer, (nrDigits == 6 ? 2 : 4)) + separator;
+              valuePointer = valuePointer + (nrDigits == 6 ? 2 : 4);
+            }
+          }
+        }
+        value = tempValue.Substring(0, tempValue.Length - 1);
+      }
+
+      return value;
+    }
+
+    private static bool NearestDate(string value, out DateTime result)
+    {
+      result = DateTime.MaxValue;
+
+#if !SILVERLIGHT
+      if (Regex.IsMatch(value, @"^\d{1,2}$", RegexOptions.Compiled))
+#else
+      if (Regex.IsMatch(value, @"^\d{1,2}$"))
+#endif
+      {
+        // Convert day-only to nearest date and return
+        int day;
+        try
+        {
+          day = Convert.ToInt32(value);
+        }
+        catch (FormatException)
+        {
+          return false;
+        }
+
+        if (day > 31)
+          return false;
+
+        DateTime tmp;
+        if (DateTime.Now.Day - day < -16)
+        {
+          if (KeepDay(new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddMonths(-1), day, out tmp))
+          {
+            result = tmp;
+            return true;
+          }
+        }
+        else if (DateTime.Now.Day - day > 16)
+        {
+          if (KeepDay(new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddMonths(1), day, out tmp))
+          {
+            result = tmp;
+            return true;
+          }
+        }
+        else
+        {
+          try
+          {
+            result = new DateTime(DateTime.Now.Year, DateTime.Now.Month, day);
+            return true;
+          }
+          catch (ArgumentOutOfRangeException)
+          {
+            return false;
+          }
+        }
+      }
+
+      return false;
+    }
+
+    private static bool KeepDay(DateTime monthYear, int day, out DateTime result)
+    {
+      try
+      {
+        result = new DateTime(monthYear.Year, monthYear.Month, day);
+        return true;
+      }
+      catch
+      {
+        result = DateTime.MinValue;
+        return false;
+      }
+    }
+  }
+}


added ValidatedNotNullAttribute to common assertions

--- Code/Light.GuardClauses/Check.CommonAssertions.cs
+++ Code/Light.GuardClauses/Check.CommonAssertions.cs
@@ -20,7 +20,7 @@
         /// <exception cref="ArgumentNullException">Thrown when <paramref name="parameter" /> is null.</exception>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")]
-        public static T MustNotBeNull<T>(this T? parameter, string? parameterName = null, string? message = null) where T : class
+        public static T MustNotBeNull<T>([ValidatedNotNull] this T? parameter, string? parameterName = null, string? message = null) where T : class
         {
             if (parameter == null)
                 Throw.ArgumentNull(parameterName, message);
@@ -35,7 +35,7 @@
         /// <exception cref="Exception">Your custom exception thrown when <paramref name="parameter" /> is null.</exception>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")]
-        public static T MustNotBeNull<T>(this T? parameter, Func<Exception> exceptionFactory) where T : class
+        public static T MustNotBeNull<T>([ValidatedNotNull] this T? parameter, Func<Exception> exceptionFactory) where T : class
         {
             if (parameter == null)
                 Throw.CustomException(exceptionFactory);
@@ -53,9 +53,8 @@
         /// <exception cref="ArgumentDefaultException">Thrown when <paramref name="parameter" /> is a value type and the default value.</exception>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")]
-        public static T MustNotBeDefault<T>(this T parameter, string? parameterName = null, string? message = null)
-        {
-#pragma warning disable CS8653 // It's ok if T is resolved to a reference type. This method is usually used in generic contexts.
+        public static T MustNotBeDefault<T>([ValidatedNotNull] this T parameter, string? parameterName = null, string? message = null)
+        {
             if (default(T) == null)
             {
                 if (parameter == null)
@@ -63,12 +62,9 @@
                 return parameter;
             }

-#pragma warning disable CS8604 // Cannot be null here
             if (EqualityComparer<T>.Default.Equals(parameter, default))
-#pragma warning restore CS8604
                 Throw.ArgumentDefault(parameterName, message);
             return parameter;
-#pragma warning restore CS8653
         }

         /// <summary>
@@ -79,9 +75,8 @@
         /// <exception cref="Exception">Your custom exception thrown when <paramref name="parameter" /> is the default value.</exception>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")]
-        public static T MustNotBeDefault<T>(this T parameter, Func<Exception> exceptionFactory)
-        {
-#pragma warning disable CS8653 // It's ok if T is resolved to a reference type. This method is usually used in generic contexts.
+        public static T MustNotBeDefault<T>([ValidatedNotNull] this T parameter, Func<Exception> exceptionFactory)
+        {
             if (default(T) == null)
             {
                 if (parameter == null)
@@ -89,12 +84,9 @@
                 return parameter;
             }

-#pragma warning disable CS8604 // Default cannot be null here
             if (EqualityComparer<T>.Default.Equals(parameter, default))
-#pragma warning restore CS8604
                 Throw.CustomException(exceptionFactory);
             return parameter;
-#pragma warning restore CS8653

         }

@@ -109,11 +101,9 @@
         /// <exception cref="ArgumentNullException">Thrown when <typeparamref name="T" /> is a reference type and <paramref name="parameter" /> is null.</exception>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")]
-        public static T MustNotBeNullReference<T>(this T parameter, string? parameterName = null, string? message = null)
-        {
-#pragma warning disable CS8653 // It's ok if T is resolved to a reference type. This method is usually used in generic contexts.
+        public static T MustNotBeNullReference<T>([ValidatedNotNull] this T parameter, string? parameterName = null, string? message = null)
+        {
             if (default(T) != null)
-#pragma warning restore CS8653
                 return parameter;

             if (parameter == null)
@@ -131,11 +121,9 @@
         /// <exception cref="Exception">Your custom exception thrown when <typeparamref name="T" /> is a reference type and <paramref name="parameter" /> is null.</exception>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")]
-        public static T MustNotBeNullReference<T>(this T parameter, Func<Exception> exceptionFactory)
-        {
-#pragma warning disable CS8653 // It's ok if T is resolved to a reference type. This method is usually used in generic contexts.
+        public static T MustNotBeNullReference<T>([ValidatedNotNull] this T parameter, Func<Exception> exceptionFactory)
+        {
             if (default(T) != null)
-#pragma warning restore CS8653
                 return parameter;

             if (parameter == null)
@@ -153,15 +141,13 @@
         /// <exception cref="ArgumentNullException">Thrown when <paramref name="parameter" /> is null.</exception>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")]
-        public static T MustBeOfType<T>(this object? parameter, string? parameterName = null, string? message = null)
+        public static T MustBeOfType<T>([ValidatedNotNull] this object? parameter, string? parameterName = null, string? message = null)
         {
             if (parameter.MustNotBeNull(parameterName, message) is T castValue)
                 return castValue;

             Throw.InvalidTypeCast(parameter, typeof(T), parameterName, message);
-#pragma warning disable CS8653 // This line of code is never reached
             return default;
-#pragma warning restore CS8653
         }

         /// <summary>
@@ -172,15 +158,13 @@
         /// <exception cref="Exception">Your custom exception thrown when <paramref name="parameter" /> cannot be cast to <typeparamref name="T" />.</exception>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")]
-        public static T MustBeOfType<T>(this object? parameter, Func<object?, Exception> exceptionFactory)
+        public static T MustBeOfType<T>([ValidatedNotNull] this object? parameter, Func<object?, Exception> exceptionFactory)
         {
             if (parameter is T castValue)
                 return castValue;

             Throw.CustomException(exceptionFactory, parameter);
-#pragma warning disable CS8653 // This line of code is never reached
             return default;
-#pragma warning restore CS8653
         }

         /// <summary>
@@ -473,7 +457,8 @@
         [ContractAnnotation("equalityComparer:null => halt")]
         public static T MustBe<T>(this T parameter, T other, IEqualityComparer<T> equalityComparer, Func<T, T, IEqualityComparer<T>, Exception> exceptionFactory)
         {
-            if (equalityComparer == null || !equalityComparer.Equals(parameter, other))
+            // ReSharper disable once ConditionIsAlwaysTrueOrFalse - caller might have NRTs turned off
+            if (equalityComparer is null || !equalityComparer.Equals(parameter, other))
                 Throw.CustomException(exceptionFactory, parameter, other, equalityComparer!);
             return parameter;
         }
@@ -540,7 +525,8 @@
         [ContractAnnotation("equalityComparer:null => halt")]
         public static T MustNotBe<T>(this T parameter, T other, IEqualityComparer<T> equalityComparer, Func<T, T, IEqualityComparer<T>, Exception> exceptionFactory)
         {
-            if (equalityComparer == null || equalityComparer.Equals(parameter, other))
+            // ReSharper disable once ConditionIsAlwaysTrueOrFalse - caller might have NRTs turned off
+            if (equalityComparer is null || equalityComparer.Equals(parameter, other))
                 Throw.CustomException(exceptionFactory, parameter, other, equalityComparer!);
             return parameter;
         }


added extension methods for char IsLetter, IsLetterOrDigit, and IsDigit

--- Code/Light.GuardClauses/Check.StringAssertions.cs
+++ Code/Light.GuardClauses/Check.StringAssertions.cs
@@ -137,6 +137,30 @@
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
 #endif
         public static bool IsWhiteSpace(this char character) => char.IsWhiteSpace(character);
+
+        /// <summary>
+        /// Checks if the specified character is a letter.
+        /// </summary>
+#if (NETSTANDARD2_0 || NETSTANDARD1_0 || NET45 || SILVERLIGHT)
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#endif
+        public static bool IsLetter(this char character) => char.IsLetter(character);
+
+        /// <summary>
+        /// Checks if the specified character is a letter or digit.
+        /// </summary>
+#if (NETSTANDARD2_0 || NETSTANDARD1_0 || NET45 || SILVERLIGHT)
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#endif
+        public static bool IsLetterOrDigit(this char character) => char.IsLetterOrDigit(character);
+
+        /// <summary>
+        /// Checks if the specified character is a digit.
+        /// </summary>
+#if (NETSTANDARD2_0 || NETSTANDARD1_0 || NET45 || SILVERLIGHT)
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#endif
+        public static bool IsDigit(this char character) => char.IsDigit(character);

         /// <summary>
         /// Ensures that the two strings are equal using the specified <paramref name="comparisonType" />, or otherwise throws a <see cref="ValuesNotEqualException" />.


Web: when language switches, change home page map language code

--- Website/OCM.MVC/Views/Home/Index.cshtml
+++ Website/OCM.MVC/Views/Home/Index.cshtml
@@ -31,7 +31,7 @@

-
+


Fix null ref exception in ChatSaver

Fix null ref exception in ChatSaver

Forgot to assign an instance variable, which lead to a crash when trying
to save chat.

--- WinterBot/WinterExtensions/ChatSaver.cs
+++ WinterBot/WinterExtensions/ChatSaver.cs
@@ -90,6 +90,7 @@
         public ChatSaver(WinterBot bot, WinterOptions options)
             : base(bot)
         {
+            m_options = options;
             m_bot = bot;
             if (!bot.Channel.Equals("zlfreebird", StringComparison.CurrentCultureIgnoreCase))
                 return;


Completed WriteAttributeValue family of functions.

--- WmcSoft.Core/Xml/XmlWriterExtensions.cs
+++ WmcSoft.Core/Xml/XmlWriterExtensions.cs
@@ -69,50 +69,146 @@
         /// <remarks>Adapted from Mark Russel's code. See http://blogs.msdn.com/b/mfussell/archive/2005/02/12/371546.aspx .</remarks>
         public static XmlWriter WriteShallowNode(this XmlWriter writer, XmlReader reader) {
             switch (reader.NodeType) {
-            case XmlNodeType.Element:
-                writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
-                writer.WriteAttributes(reader, true);
-                if (reader.IsEmptyElement)
-                    writer.WriteEndElement();
-                break;
-            case XmlNodeType.Text:
-                writer.WriteString(reader.Value);
-                break;
-            case XmlNodeType.Whitespace:
-            case XmlNodeType.SignificantWhitespace:
-                writer.WriteWhitespace(reader.Value);
-                break;
-            case XmlNodeType.CDATA:
-                writer.WriteCData(reader.Value);
-                break;
-            case XmlNodeType.EntityReference:
-                writer.WriteEntityRef(reader.Name);
-                break;
-            case XmlNodeType.XmlDeclaration:
-            case XmlNodeType.ProcessingInstruction:
-                writer.WriteProcessingInstruction(reader.Name, reader.Value);
-                break;
-            case XmlNodeType.DocumentType:
-                writer.WriteDocType(reader.Name, reader.GetAttribute("PUBLIC"), reader.GetAttribute("SYSTEM"), reader.Value);
-                break;
-            case XmlNodeType.Comment:
-                writer.WriteComment(reader.Value);
-                break;
-            case XmlNodeType.EndElement:
-                writer.WriteFullEndElement();
-                break;
+                case XmlNodeType.Element:
+                    writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
+                    writer.WriteAttributes(reader, true);
+                    if (reader.IsEmptyElement)
+                        writer.WriteEndElement();
+                    break;
+                case XmlNodeType.Text:
+                    writer.WriteString(reader.Value);
+                    break;
+                case XmlNodeType.Whitespace:
+                case XmlNodeType.SignificantWhitespace:
+                    writer.WriteWhitespace(reader.Value);
+                    break;
+                case XmlNodeType.CDATA:
+                    writer.WriteCData(reader.Value);
+                    break;
+                case XmlNodeType.EntityReference:
+                    writer.WriteEntityRef(reader.Name);
+                    break;
+                case XmlNodeType.XmlDeclaration:
+                case XmlNodeType.ProcessingInstruction:
+                    writer.WriteProcessingInstruction(reader.Name, reader.Value);
+                    break;
+                case XmlNodeType.DocumentType:
+                    writer.WriteDocType(reader.Name, reader.GetAttribute("PUBLIC"), reader.GetAttribute("SYSTEM"), reader.Value);
+                    break;
+                case XmlNodeType.Comment:
+                    writer.WriteComment(reader.Value);
+                    break;
+                case XmlNodeType.EndElement:
+                    writer.WriteFullEndElement();
+                    break;
             }
             return writer;
         }

         #region WriteAttributeValue

+        public static void WriteAttributeValue(this XmlWriter writer, string prefix, string localName, string ns, double value) {
+            writer.WriteStartAttribute(prefix, localName, ns);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+        public static void WriteAttributeValue(this XmlWriter writer, string localName, string ns, double value) {
+            writer.WriteStartAttribute(localName, ns);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+        public static void WriteAttributeValue(this XmlWriter writer, string localName, double value) {
+            writer.WriteStartAttribute(localName);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+
+        public static void WriteAttributeValue(this XmlWriter writer, string prefix, string localName, string ns, float value) {
+            writer.WriteStartAttribute(prefix, localName, ns);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+        public static void WriteAttributeValue(this XmlWriter writer, string localName, string ns, float value) {
+            writer.WriteStartAttribute(localName, ns);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+        public static void WriteAttributeValue(this XmlWriter writer, string localName, float value) {
+            writer.WriteStartAttribute(localName);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+
+        public static void WriteAttributeValue(this XmlWriter writer, string prefix, string localName, string ns, decimal value) {
+            writer.WriteStartAttribute(prefix, localName, ns);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+        public static void WriteAttributeValue(this XmlWriter writer, string localName, string ns, decimal value) {
+            writer.WriteStartAttribute(localName, ns);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+        public static void WriteAttributeValue(this XmlWriter writer, string localName, decimal value) {
+            writer.WriteStartAttribute(localName);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+
+        public static void WriteAttributeValue(this XmlWriter writer, string prefix, string localName, string ns, int value) {
+            writer.WriteStartAttribute(prefix, localName, ns);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+        public static void WriteAttributeValue(this XmlWriter writer, string localName, string ns, int value) {
+            writer.WriteStartAttribute(localName, ns);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+        public static void WriteAttributeValue(this XmlWriter writer, string localName, int value) {
+            writer.WriteStartAttribute(localName);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+
+        public static void WriteAttributeValue(this XmlWriter writer, string prefix, string localName, string ns, long value) {
+            writer.WriteStartAttribute(prefix, localName, ns);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+        public static void WriteAttributeValue(this XmlWriter writer, string localName, string ns, long value) {
+            writer.WriteStartAttribute(localName, ns);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+        public static void WriteAttributeValue(this XmlWriter writer, string localName, long value) {
+            writer.WriteStartAttribute(localName);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+
+        public static void WriteAttributeValue(this XmlWriter writer, string prefix, string localName, string ns, DateTimeOffset value) {
+            writer.WriteStartAttribute(prefix, localName, ns);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+        public static void WriteAttributeValue(this XmlWriter writer, string localName, string ns, DateTimeOffset value) {
+            writer.WriteStartAttribute(localName, ns);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+        public static void WriteAttributeValue(this XmlWriter writer, string localName, DateTimeOffset value) {
+            writer.WriteStartAttribute(localName);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+
         public static void WriteAttributeValue(this XmlWriter writer, string prefix, string localName, string ns, bool value) {
             writer.WriteStartAttribute(prefix, localName, ns);
             writer.WriteValue(value);
             writer.WriteEndAttribute();
         }
-         public static void WriteAttributeValue(this XmlWriter writer, string localName, string ns, bool value) {
+        public static void WriteAttributeValue(this XmlWriter writer, string localName, string ns, bool value) {
             writer.WriteStartAttribute(localName, ns);
             writer.WriteValue(value);
             writer.WriteEndAttribute();
@@ -123,6 +219,38 @@
             writer.WriteEndAttribute();
         }

-       #endregion
+        public static void WriteAttributeValue(this XmlWriter writer, string prefix, string localName, string ns, DateTime value) {
+            writer.WriteStartAttribute(prefix, localName, ns);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+        public static void WriteAttributeValue(this XmlWriter writer, string localName, string ns, DateTime value) {
+            writer.WriteStartAttribute(localName, ns);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+        public static void WriteAttributeValue(this XmlWriter writer, string localName, DateTime value) {
+            writer.WriteStartAttribute(localName);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+
+        public static void WriteAttributeValue(this XmlWriter writer, string prefix, string localName, string ns, object value) {
+            writer.WriteStartAttribute(prefix, localName, ns);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+        public static void WriteAttributeValue(this XmlWriter writer, string localName, string ns, object value) {
+            writer.WriteStartAttribute(localName, ns);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+        public static void WriteAttributeValue(this XmlWriter writer, string localName, object value) {
+            writer.WriteStartAttribute(localName);
+            writer.WriteValue(value);
+            writer.WriteEndAttribute();
+        }
+
+        #endregion
     }
 }


20170317不不不

--- ezSmartHome/WebService/Controllers/HomeController.cs
+++ ezSmartHome/WebService/Controllers/HomeController.cs
@@ -53,6 +53,37 @@

             return View();
         }
+        public static string AESDecrypt(String Data, String Key)
+        {
+            Byte[] encryptedBytes = Convert.FromBase64String(Data);
+            Byte[] bKey = new Byte[32];
+            Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length);
+
+            MemoryStream mStream = new MemoryStream(encryptedBytes);
+            //mStream.Write( encryptedBytes, 0, encryptedBytes.Length );
+            //mStream.Seek( 0, SeekOrigin.Begin );
+            RijndaelManaged aes = new RijndaelManaged();
+            aes.Mode = CipherMode.ECB;
+            aes.Padding = PaddingMode.PKCS7;
+            aes.KeySize = 128;
+            aes.Key = bKey;
+            //aes.IV = _iV;
+            CryptoStream cryptoStream = new CryptoStream(mStream, aes.CreateDecryptor(), CryptoStreamMode.Read);
+            try
+            {
+                byte[] tmp = new byte[encryptedBytes.Length + 32];
+                int len = cryptoStream.Read(tmp, 0, encryptedBytes.Length + 32);
+                byte[] ret = new byte[len];
+                Array.Copy(tmp, 0, ret, 0, len);
+                return Encoding.UTF8.GetString(ret);
+            }
+            finally
+            {
+                cryptoStream.Close();
+                mStream.Close();
+                aes.Clear();
+            }
+        }

         [HttpPost]
         public ActionResult UserProfile(FormCollection collection)
@@ -62,6 +93,12 @@

         public ActionResult OpenService(string state)
         {
+
+            //Base64.encode(Aes.encrypt(AesKey,{ "userid":"用户标识","operation":"open/close","timestamp":"时间戳，毫秒","appid":"应用的APPID"}))
+            byte[] bytes = Convert.FromBase64String(state);
+            string unSec = Encoding.UTF8.GetString(bytes);
+
+
             var req = Newtonsoft.Json.JsonConvert.DeserializeObject<StateEntity>(state);
             runLog.log("open :"+state);