I ran two different benchmark tests to demonstrate different approaches for updating a WinForms TextBox. I built a simple form a rich text box. On separate runs, I filled the text box with text as shown below:

// The += approach:

richTextBox1.Text = string.Empty;
for (int i = 0; i < 1000; i++)
{
    richTextBox1
.Text += "Hello, World!\r\n";
}

// The StringBuilder approach:

richTextBox2.Text = string.Empty;
var builder = new StringBuilder();
for (int i = 0; i < 1000; i++)
{
    builder
.AppendLine("Hello, World!\r\n");
    richTextBox2
.Text = builder.ToString();
}

The AppendText() approach

richTextBox3.Text = string.Empty;
for (int i = 0; i < 1000; i++)
{
    richTextBox3
.AppendText("Hello, World!");
}

And the results on my old machine?

  • += Approach: 10.7470703 seconds.
  • StringBuilder: 10.7353515 seconds.
  • AppendText(): 0.7041015 seconds.

I ran another benchmark. I filled a text box with 10MB of dummy text, then used the three approaches to append "Hello, World!" to the text box.

And the results of this?

  • += Approach: 11.7470703 seconds.
  • StringBuilder: 12.0615235 seconds.
  • AppendText(): 0.1142578 seconds.

Conclusion: It is much faster to append to a text box using AppendText() than to assign text using string concatenation or from an intermediate data store such as s StringBuilder. Also note that the update rate drops substantially (9 per second) when the text box contained 10MB of text. Depending on the circumstances, a form designer might use multi-threading and caching (via StringBuilder) of text in chunks to reduce the frequency of updates required in the text box.

Note that the .NET text box is a wrapper of the Win32 text box which doesn't use immutable strings, thus giving it this edge in appending performance.


 
Categories: C# | Windows Forms

Sometimes it happens that SharePoint provides exceptionally long addresses for pages. If it also happens to be that when adding such a long hyperlink to the Quick Launch, that the link will exceed the 255 character limit to addresses in the Quick Launch. This post addresses strategies to shorten long SharePoint URLs into something a little more manageable.

Take, for example, a typical link to the NewForm.aspx file we get when clicking New Item on a list or document library (shown on multiple lines for convenience):

http://share.demo.com/sites/ExampleSPSiteDemo/Lists/Document%20LibExamples/NewForm.aspx?RootFolder=%2Fsites%2FExampleSPSiteDemo%2FLists%2FDocument%20LibExamples&Source=http%3A%2F%2Fshare%2Edemo%2Ecom%2Fsites%2FExampleSPSiteDemo%2FLists%2FDocument%2520LibExamples%2FAllItems%2Easpx

This obscenely long URL winds up getting truncated when typed or pasted into the quick launch, turning out like:

http://share.demo.com/sites/ExampleSPSiteDemo/Lists/Document%20LibExamples/NewForm.aspx?RootFolder=%2Fsites%2FExampleSPSiteDemo%2FLists%2FDocument%20LibExamples&Source=http%3A%2F%2Fshare%2Edemo%2Ecom%2Fsites%2FExampleSPSiteDemo%2FLists%2FDocument%2520LibE

Oftentimes, an adequate solution is to trim the unwanted muck from the address. Here are some ideas:

  1. Remove the protocol (http://) and host name (share.demo.com) from the URL. The result is an address that starts with a slash (/) and, as a side benefit, improves your administrator's ability to do some maintenance tasks.
    • In this case, removing the protocol and host saves us 21 characters, which is enough to solve the problem at hand, but might be inadequate to completely solve the problem with exceptionally long addresses.
  2. Remove unwanted query string values. The query string is everything after the question mark (?). Query strings are usually formatted like ?key1=value1&key2=value2&key3=value3&..., where each of the values might appear to be gibberish. In the case of the address above, there are two keys: RootFolder, and Source.
    • RootFolder determines which folder will receive the new item. If your list does not use folders, feel free to strip out everything from the word RootFolder to the next ampersand (&).
    • Source determines where the browser should go after the item is inserted. The default source is the default view of the list or library. If redirecting to the default view is not inappropriate, strip out the Source key and value.
    • If you strip out all the keys and values, you can delete the question mark as well.

Supposing you do all the suggested reductions, the URL now looks like this:

/sites/ExampleSPSiteDemo/Lists/Document%20LibExamples/NewForm.aspx

...Which is well under the 255 character Quick Launch limit, and is easier for a real human to digest, anyway.


 
Categories: SharePoint

Welcome to part 3 in the Powerful Extension Methods series. This article takes a look at a common class in ASP.NET, the System.Web.UI.WebControls.ListItemCollection. The ListItemCollection is used in many places: the ListBox, DropDownList, CheckBoxList, and RadioButtonList all store their items in this type of collection.

ListItemCollection implements IEnumerable, but not the strongly typed IEnumerable<ListItem>. Many collections throughout the base class libraries are that way. One of the disadvantages of implementing only IEnumerable is that when you want to process the collection using LINQ, you must first cast the collection to the desired type. Something like this:

items.Cast<ListItem>()

The Cast<TResult>() function gets called implicitly in LINQ expressions such as this:

var selectedItems = from ListItem item in items
                    where item.Selected
                    select item;

The query feels slightly less elegant when written using the LINQ methods directly.

var selectedItems = items.Cast<TResult>().Where(item => item.Selected);

Adding a quick extension method like the one below allows calls to the Where<TResult>() method without including the inelegant call to Cast<TResult>().

/// <summary>
/// Filters a <c>ListItemCollection</c> based on a predicate.
/// </summary>
/// <param name="items">The <c>ListItemCollection</c> to filter.</param>
/// <param name="predicate">A function to test each element for a condition.</param>
/// <returns>An enumerable set of list items filtered by the predicate.</returns>
public static IEnumerable<ListItem> Where(this ListItemCollection items, Func<ListItem, bool>
                                          predicate)
{
  return items.Cast<ListItem>().Where(predicate);
}

This allows the simpler call:

var selectedItems = items.Where(item => item.Selected);

The ASP.NET ListItemCollection does not ship with a SelectedItems or SelectedIndices property. We can elegantly compensate for the missing property with two short extension methods.

/// <summary>
/// Filters a <c>ListItemCollection</c> based on whether the item is selected.
/// </summary>
/// <param name="items">The <c>ListItemCollection</c> to filter.</param>
/// <returns>An enumerable set of list items filtered by whether the item is selected.</returns>
public static IEnumerable<ListItem> WhereSelected(this ListItemCollection items)
{
  return items.Cast<ListItem>().Where(i => i.Selected);
}

/// <summary>
/// Filters a <c>ListItemCollection</c> based on whether the item is not selected.
/// </summary>
/// <param name="items">The <c>ListItemCollection</c> to filter.</param>
/// <returns>An enumerable set of list items filtered by whether the item is not selected.</returns>
public static IEnumerable<ListItem> WhereNotSelected(this ListItemCollection items)
{
  return items.Cast<ListItem>().Where(i => !i.Selected);
}

Often times, it is not the list items themselves that we are interested in, but only their values. A few brief extension methods make for an elegant way to retrieve SelectedValues.

/// <summary>
/// Filters a <c>ListItemCollection</c> based on whether the item is selected, and retrieves each
value.
/// </summary>
/// <param name="items">The <c>ListItemCollection</c> to filter.</param>
/// <returns>An enumerable set of list items filtered by whether the item is selected.</returns>
public static IEnumerable<string> ValuesWhereSelected(this ListItemCollection items)
{
  return items.Cast<ListItem>().Where(i => i.Selected).Select(i => i.Value);
}

/// <summary>
/// Filters a <c>ListItemCollection</c> based on whether the item is not selected, and retrieves
each value.
/// </summary>
/// <param name="items">The <c>ListItemCollection</c> to filter.</param>
/// <returns>An enumerable set of list items filtered by whether the item is not selected.</returns>
public static IEnumerable<string> ValuesWhereNotSelected(this ListItemCollection items)
{
  return items.Cast<ListItem>().Where(i => !i.Selected).Select(i => i.Value);
}

Collecting selected values is helpful, but setting selected values is also helpful. The next two extension methods enable selecting multiple items provided a list of values or a Lambda expression predicate.

/// <summary>
/// Sets each element in the collection as selected based on whether the item is contained in the
set of values.
/// </summary>
/// <param name="items">The items to update.</param>
/// <param name="values">The values to select. All other items will be deselected.</param>
public static void SetAllSelectedByValue(this ListItemCollection items, IEnumerable<string> values)
{
  var hashValues = new HashSet<string>(values);
  if (values == null)
  {
    items.SetAllSelectedIf(i => false);
  }
  else
  {
    items.SetAllSelectedIf(i => hashValues.Contains(i.Value));
  }
}

/// <summary>
/// Sets each element in the collection as selected based on a predicate.
/// </summary>
/// <param name="items">The items to update.</param>
/// <param name="predicate">A function to test each element for a condition, and update the selected
                status of the element to the test result.</param>
public static void SetAllSelectedIf(this ListItemCollection items, Func<ListItem, bool> predicate)
{
  foreach (ListItem item in items)
  {
    item.Selected = predicate(item);
  }
}

These few extension methods don't perform any earth-shaking operations, but they do provide a clean, elegant way to operate on ListItemCollection objects.

Happy Coding!


 
Categories: ASP.NET | C# | Extension Methods

Welcome to part 2 of the Powerful Extension Methods series. Today, we take a look at XML serialization. If you have ever used the .NET XmlSerializer class, you know how powerful it is. Decorate your class with appropriate attributes, and you can generate or parse complex XML structures without having to write any XML parsing code.

To find out more about .NET and XML serialization, check out the documentation here. If you want to see excellent examples of the XmlSerializer in action, check out the code of DasBlog and look at what they do with RSS and Atom feeds. It's pretty neat.

It doesn't take long, working with the XmlSerializer, before the good ol' DRY principle drives us to create serialization helper classes, like Andrew Gunn created. Utility classes are usually perfect candidates for extension methods.

So here we go: one extension method for serializing any object (if it is not serializable, expect an exception), and a generic method each for deserializing streams, strings, and XmlNodes.

/// <summary>
/// This class provides extension methods related to serialization.
/// </summary>
public static class SerializationExtensions
{
  /// <summary>
  /// Serializes an object as XML.
  /// </summary>
  /// <param name="value">The object to serialize.</param>
  /// <returns>An XML string representing the serialized object.</returns>
  public static string SerializeAsXml(this object value)
  {
      var ser = new XmlSerializer(value.GetType());
      using (var stream = new MemoryStream())
      using (var xmlwriter = new XmlTextWriter(stream, Encoding.UTF8))
      {
          ser.Serialize(xmlwriter, value);
          var buffer = stream.GetBuffer();

          // skip the byte order mask
          return Encoding.UTF8.GetString(buffer, 3, buffer.Length - 3);
      }
  }

  /// <summary>
  /// Deserializes the specified string using an XML serializer.
  /// </summary>
  /// <typeparam name="T">The type of object to deserialize.</typeparam>
  /// <param name="stream">The stream to deserialize.</param>
  /// <returns>A deserialized object of the specified type.</returns>
  public static T Deserialize<T>(this Stream stream)
  {
    using (var reader = new XmlTextReader(reader))
    {
      var ser = new XmlSerializer(typeof(T));
      return (T)ser.Deserialize(reader);
    }
  }

  /// <summary>
  /// Deserializes the specified string using an XML serializer.
  /// </summary>
  /// <typeparam name="T">The type of object to deserialize.</typeparam>
  /// <param name="xml">The XML to deserialize.</param>
  /// <returns>A deserialized object of the specified type.</returns>
  public static T Deserialize<T>(this string xml)
  {
    using (var reader = new StringReader(xml))
    {
      var ser = new XmlSerializer(typeof(T));
      return (T)ser.Deserialize(reader);
    }
  }

  /// <summary>
  /// Deserializes the specified node using an XML serializer.
  /// </summary>
  /// <typeparam name="T">The type of object to deserialize.</typeparam>
  /// <param name="node">The node containing XML to deserialize.</param>
  /// <returns>A deserialized object of the specified type.</returns>
  public static T Deserialize<T>(this XmlNode node)
  {
    using (var reader = new StringReader(node.OuterXml))
    {
      var ser = new XmlSerializer(typeof(T));
      return (T)ser.Deserialize(reader);
    }
  }
}

Happy Coding!


 
Categories: C# | Extension Methods

Welcome to part 1 of the Powerful Extension Methods series. The extension method concept is an excellent feature of the latest breeds of the .NET framework. They allow us to abstract away static utility classes in a way that makes the utility methods appear to belong to the object they operate upon. Beginners can check things out here and here for a good introduction.

I do WinForms programming from time to time. In any Windows application, whether through traditional WinForms or through WPF, managing event handling in the face of threading is critical. Exceptions are thrown when code updates any UI Control property from any thread except the thread that created the control. This problem surfaces when some background thread needs to update the UI.

This led to a lot of creative solutions involving InvokeRequired and Invoke. One solution involves creating an event on the threaded object which the UI can subscribe to. The OnMyEvent method of the object handles invoking each event handler methods on the thread from which they subscribed. The full idea is described here.

It only took me an event handler or two before the DRY principle screamed for attention. Enter, the SafeInvoke extension method:

/// <summary>
/// Raises the event asynchronously.
/// </summary>
/// <param name="handler">The handler.</param>
/// <param name="source">The source.</param>
/// <param name="args">The <see cref="System.EventArgs"/> instance containing the event data.</param>
public static void SafeInvoke(this EventHandler handler, object source, EventArgs args)
{
  if (handler != null)
  {
    foreach (EventHandler singleCast in handler.GetInvocationList())
    {
      var syncInvoke = singleCast.Target as ISynchronizeInvoke;
      try
      {
        if (syncInvoke != null && syncInvoke.InvokeRequired)
        {
          syncInvoke.Invoke(singleCast, new object[] { source, args });
        }
        else
        {
          singleCast(source, args);
        }
      }
      catch
      {
        // Do nothing. The event handler may have been detached asynchronously.
      }
    }
  }
}

With this extension method, we can construct our threaded object to look something like this:

public class MyWorker
{
  public event EventHandler SomeEvent;

  protected virtual void OnSomeEvent(EventArgs e)
  {
    this.SomeEvent.SafeInvoke(this, e);
  }
}

You can see that using this pattern, the event will manage on its own the process of ensuring the event is handled on the subscribing threads. No more threading exceptions when updating the UI from a background worker!

Another common event delegate that deserves a similar extension method is the generic EventHandler<T> class. The model of the function is no surprise; but, here it is in full.

/// <summary>
/// Raises the event asynchronously.
/// </summary>
/// <typeparam name="T">The type of the event handler arguments</typeparam>
/// <param name="handler">The handler.</param>
/// <param name="source">The source.</param>
/// <param name="args">The arguments containing the event data.</param>
public static void SafeInvoke<T>(this EventHandler<T> handler, object source, T args)
where T : EventArgs { if (handler != null) { foreach (EventHandler<T> singleCast in handler.GetInvocationList()) { var syncInvoke = singleCast.Target as ISynchronizeInvoke; try { if (syncInvoke != null && syncInvoke.InvokeRequired) { syncInvoke.Invoke(singleCast, new object[] { source, args }); } else { singleCast(source, args); } } catch { // Do nothing. The event handler may have been detached asynchronously. } } } }

Happy Coding!


 
Categories: C# | Extension Methods