RSS Feed
Mar 2

A singleton base class to implement the singleton pattern in C#

Posted on Tuesday, March 2, 2010 in Programming

The singleton design pattern is one of the most controversial pattern. Some people even call it anti-pattern, evil, or stupid. I won’t go into the debate now, but I just want to share something for those who need to use singletons.

Although it is one of the easiest pattern to understand, it is also very easy to code it poorly, leading to unexpected side effects such as poor performance or being not thread-safe.

Jon Skeet has written a very good article describing different implementations of the singleton pattern in C#. He gives a nice example on how you can write a singleton code that is thread-safe and lazy-instantiating. The code is less than 20 lines and you can use it as a template for your singletons.

Since in some projects I have created several singleton objects, it started to get repetitive. Therefore I decided to write a base class based on this pattern as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
using System;
using System.Globalization;
using System.Reflection;
 
public abstract class SingletonBase<T> where T : class
{
  /// <summary>
  /// A protected constructor which is accessible only to the sub classes.
  /// </summary>
  protected SingletonBase() { }
 
  /// <summary>
  /// Gets the singleton instance of this class.
  /// </summary>
  public static T Instance
  {
    get { return SingletonFactory.Instance; }
  }
 
  /// <summary>
  /// The singleton class factory to create the singleton instance.
  /// </summary>
  class SingletonFactory
  {
    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static SingletonFactory() { }
 
    // Prevent the compiler from generating a default constructor.
    SingletonFactory() { }
 
	internal static readonly T Instance = GetInstance();
 
    static T GetInstance()
    {
      var theType = typeof(T);
 
      T inst;
 
      try
      {
        inst = (T)theType
          .InvokeMember(theType.Name,
            BindingFlags.CreateInstance | BindingFlags.Instance
            | BindingFlags.NonPublic,
            null, null, null,
            CultureInfo.InvariantCulture);
      }
      catch (MissingMethodException ex)
      {
        throw new TypeLoadException(string.Format(
          CultureInfo.CurrentCulture,
          "The type '{0}' must have a private constructor to " +
          "be used in the Singleton pattern.", theType.FullName)
          , ex);
      }
 
      return inst;
    }
  }
}

For an example of usage, we will create a singleton class that generates a sequence number:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Must seal the class so no sub-classes can be defined.
public sealed class SequenceGeneratorSingleton
  : SingletonBase<SequenceGeneratorSingleton>
{
  // Must have a private constructor so no instance can be created externally.
  SequenceGeneratorSingleton()
  {
    _number = 0;
  }
 
  private int _number;
 
  public int GetSequenceNumber()
  {
	return _number++;
  }
}

Then, a console application will call the sequence generator class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Program
{
  static void Main(string[] args)
  {
    Console.WriteLine("Sequence: " + SequenceGeneratorSingleton.Instance
	  .GetSequenceNumber().ToString());  // Print "Sequence: 0"
 
    Console.WriteLine("Sequence: " + SequenceGeneratorSingleton.Instance
	  .GetSequenceNumber().ToString());  // Print "Sequence: 1"
 
    Console.WriteLine("Sequence: " + SequenceGeneratorSingleton.Instance
	  .GetSequenceNumber().ToString());  // Print "Sequence: 2"
  }
}

To recap, in order to create a singleton class using the singleton base class, you need to do the following:

  1. Define a sealed class which derives from SingletonBase<T>, where T is the class name you are defining. It ensures that you cannot create subclasses from this singleton class.
  2. Define a single parameterless private constructor inside the class. It ensures that no instances of this class can be created externally.
  3. Access the class’ singleton instance and public members by calling the Instance property.

I have also included the code in LiquidSilver, which you can view or download from the repository.

Feb 8

Refreshing the LINQ to SQL DataContext by Clearing the Cache

Posted on Monday, February 8, 2010 in Programming

LINQ to SQL DataContext can sometimes be difficult to deal with. Especially when combined with the use of stored procedures. For example, there is a case where I want to delete multiple records with a stored procedure rather than using the LINQ to SQL API for performance reason. After executing the stored procedure, the DataContext is not aware of the changes and still thinks that the entities are still there because the DataContext caches them. Hence, when I try to add another record using the same key, the DataContext throws an exception with the following message:

Cannot add an entity with a key that is already in use.

Logically, I want to refresh the DataContext memory so it will recheck the database. The provided DataContext.Refresh() method requires the original entity set to be sent which can be a problem. I don’t want to query the DataContext for the entities for performance reason, hence the stored procedure is used in the first place. So I have to find another way to refresh the DataContext or clear the cache without relying on the original entity set.

There is no official way to do it, but I stumbled on this blog post telling that there is a DataContext method called ClearCache() that can be used for that purpose. Unfortunately that method has internal modifier so you cannot call it from your code. But with a bit of reflection magic you can borrow the hidden power as follows:

context.GetType().InvokeMember(
	"ClearCache",
	BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
	null, context, null);

After invoking the ClearCache() method, I can now successfully add new entities to the DataContext by reusing the keys from the deleted records.

Jan 6

LiquidSilver 0.1.0.0 Released

Posted on Wednesday, January 6, 2010 in News, Programming

LiquidSilver 0.1.0.0 has been released on Codeplex. This is still a beta version but the functionalities are quite complete and I have used many parts of it in production environment.

If you want to try it, you can download the code and binary from Codeplex. Kindly submit bug reports to the issue tracker.

If you haven’t done so, you may read the introduction to LiquidSilver or visit the resource page.

Dec 30

Working with SharePoint Lists in LiquidSilver

Posted on Wednesday, December 30, 2009 in Programming

In this post, I’ll cover some common operations on SharePoint lists which you can simplify with LiquidSilver. For this purpose, I continue using the Actors list we created earlier.

1. Clearing all items in a list

One day, Katie — one of Tom’s client — came by and asked whether she could empty the Actors list in one go instead of deleting each item individually, which was, of course, pretty tedious. Wanting to impress this cute woman, Tom said promptly that it was a piece of cake, he just needed an hour or two to provide this functionality.

Tom decided to customize the toolbar to include a Clear All Items command in the menu. He didn’t know how to do it yet, so he asked his good friend, Google, that led him to a helpful blog post. Tom was successful and happy to create the shiny new menu under an hour, then he started to code the implementation.

Being a smart codebender, Tom knew he just needed to find the Empty() or ClearItems() method of the particular SPList object. Unfortunately, they didn’t exist. Tom could only see a Delete() method which he knew that it would delete the list, not the items. Then he typed SPList.Items.Clear() instead. Nice try, but it also didn’t exist. “Well, let’s do it in old-fashioned way!” Tom said to himself. He quickly wrote and compiled this piece of code in the editor:

foreach (SPListItem item in list.Items)
{
  item.Delete();
}

Too bad when he ran it, it threw an exception saying: “Collection was modified; enumeration operation may not execute.” He was smart enough to figure out how this happened and quickly rewrote the code as follow:

var items = list.Items.Cast&lt;SPListItem&gt;().ToList();
var count = items.Count;
for (int i = count - 1; i &gt;=0; i--)
{
  items[i].Delete();
}

Thanks to LINQ, he could fix it with only two more lines. Almost two hours had passed when he heard someone approaching, this must be Katie. Just in time when Katie asked him about her little request, Tom finished with his testing and packaging. With a big smile he said that everything was fine and he was ready to deliver the feature right away. Katie looked happy and she went back to her workstation to try the feature.

While Tom was packing to leave for the day, his phone rang, it was Katie. Excitedly he picked up the phone, little did he know that Katie was upset because the deletion process was so slow it crashed the server. Tom asked her, how many records she was trying to delete. She said there were several thousands of records.

Tom realized that his approach was sub-optimal. He already knew from the SharePoint coding best practice guideline that accessing the Items property should be avoided. Furthermore, to access more than 2000 items, pagination should be used. Tom also knew that to process a lot of items at once, it was better to use the ProcessBatchData method than deleting the items one at a time. But the batch processing requires a proper CAML query to be constructed and it is ugly. He ended up spending a couple more hours to implement all these things.

Tom was kind enough, though, that he didn’t want others to go through this. He decided to put his implementation in a way to be usable by everyone else and push the code to the open source LiquidSilver SharePoint Framework. So now, we can use the following code to clear all items from a list easily and efficiently:

bool continueOnError = true;
new HgList(web.Lists["list name"]).ClearItems(continueOnError);

2. Batch updating items in a list

The ProcessBatchData method is not only useful for deleting multiple items in a batch. An MSDN article shows that it can be used for batch updating list items, too. It is a faster and preferred way to update multiple items in a list.

Unfortunately, once again you have to deal with the cryptic CAML query as shown in the article. While he was at it, Tom had the chance to create a nice wrapper function, though. For example, we want to change the titles of all items in the Actors list by making them uppercase. With LiquidSilver, you can code like this:

// Prepare a list of HgBatchItemDictionary objects.
var batchItems = new List();
 
var items = list.Items;
foreach (SPListItem item in items)
{
  // The HgBatchItemDictionary constructor takes the item's ID as the
  // parameter.
  var batchItem = new HgBatchItemDictionary(item.ID);
 
  // HgBatchItemDictionary uses key-value pairs to specify the field and
  // the field's value of the item.
  batchItem["Title"] = item.Title.ToUpper();
 
  batchItems.Add(batchItem);
}
 
// Continue the batch process even though there is an error.
bool continueOnError = true;
 
new HgList(web.Lists["list name"])
  .BatchUpdate(continueOnError, batchItems.ToArray());

As seen in the code, we need to represent the items we want to update as HgBatchItemDictionary objects. It is a dictionary that uses the key to represent the item’s field (by specifying the field’s internal name), and the value to represent the item’s field’s value. You need to specify only the fields you want to update. HgBatchItemDictionary requires the item’s ID that can be provided using the constructor or the ItemId property.

You may have noticed that HgList is an object that wrap an SPList object, like the HgListItem object to the SPListItem object, which is demonstrated in the previous article. Please check other related articles if you are interested. Thanks.

Dec 23

Getting Started with LiquidSilver

Posted on Wednesday, December 23, 2009 in Programming

What is LiquidSilver? If you don’t know about it yet, I suggest you read the short introduction post first.

1. Getting the source code

Before anything, you need to download the LiquidSilver source code from CodePlex. Currently there’s only one change set available. I still have some more updates on my private repository that needs some clean ups and more commenting before uploading to CodePlex. But this change set is already usable.

2. Building the project

After downloading, you can open the solution in Visual Studio 2008 (SP1 is recommended). Ensure that the project maintains the references to Microsoft.SharePoint.dll and Microsoft.SharePoint.Security.dll properly. You may need to assign a strong name key to the project. After everything is in order, you can start to build the project. If the build is successful, it will produce LiquidSilver.dll in the project output folder.

3. Setting up your SharePoint site

Now, we need to set up a SharePoint site for our playground. You can create a new site or use an existing one. You can use either WSS 3.0 or MOSS 2007. In that site, create a new list called Actors. It doesn’t matter whether you want to create a list definition or just create a new custom list from SharePoint UI. In the list, define the following columns:

Column Name Column Type
Title Single line of text
Dob Date and Time; Date and Time Format: Date Only
Spouse Lookup; Get information from: Actors; In this column: Title

This is enough for now. While you can use the SharePoint built-in UI to add items to the list, we will do it programmatically.

4. Adding an item programmatically with SharePoint API

I totally believe you all know how to do this. I write this section only as a comparison. For this purpose, let’s fire up Visual Studio 2008, create a new console project. To be practical, ensure you have Visual Studio 2008 in the same box with the SharePoint installation.

Open the Program.cs file and write the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using System;
using Microsoft.SharePoint;
 
namespace TestConsole
{
  class Program
  {
    const string SiteUrl = "http://your-server-url";
    const string ListName = "Actors";
 
    static void Main(string[] args)
    {
      using (var site = new SPSite(SiteUrl))
      {
        using (var web = site.OpenWeb())
        {
          var list = web.Lists[ListName];
 
          var tom = list.Items.Add();
          tom["Title"] = "Tom Cruise";
          tom["Dob"] = new DateTime(1962, 7, 3);
          tom.Update();
 
          var katie = list.Items.Add();
          katie = list.Items.Add();
          katie["Title"] = "Katie Holmes";
          katie["Dob"] = new DateTime(1978, 12, 18);
          katie["Spouse"] = new SPFieldLookupValue(tom.ID, tom.Title);
          katie.Update();
 
          tom["Spouse"] = new SPFieldLookupValue(katie.ID, katie.Title);
          tom.Update();
        }
      }
    }
  }
}

The code adds two items to the Actors list. It is very straight-forward and easy. Really? Well for simple column types like text, boolean, numbers, and date & time, you can simply assign the C# standard type variables to the item’s fields. But for more complex types like user & group, lookup,  or URL, there can be some problems. Certain types require different methods of setting and getting the values to or from a field. Like in the code above, it requires instantiating an SPFieldLookupValue object to assign a value to a lookup field. For other complex types, it requires different objects and different techniques. Even the way to set and get the value is sometimes different. This is not intuitive and, for some people, it’s quite hard to guess how to do it without the help of Google.

Let’s see how LiquidSilver can help you with this.

5. Adding an item programmatically with LiquidSilver

You can open the same project or create a new one, it doesn’t matter. Either way, you need to add a reference to LiquidSilver.dll which you have built in step 2 earlier. Then, modify the code inside Program.cs as follow:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using System;
using LiquidSilver;
using Microsoft.SharePoint;
 
namespace TestConsole
{
  class Program
  {
    const string SiteUrl = "http://your-server-url";
    const string ListName = "Actors";
 
    static void Main(string[] args)
    {
      using (var site = new SPSite(SiteUrl))
      {
        using (var web = site.OpenWeb())
        {
          var list = web.Lists[ListName];
 
          var tom = new HgListItem(list.Items.Add());
          tom.Title = "Tom Cruise";
          tom.SetDate("Dob", new DateTime(1962, 7, 3));
          tom.Update();
 
          var katie = new HgListItem(list.Items.Add());
          katie.Title = "Katie Holmes";
          katie.SetDate("Dob", new DateTime(1978, 12, 18));
          katie.SetLookup("Spouse", tom.ID, tom.Title);
          katie.Update();
 
          tom.SetLookup("Spouse", katie.ID, katie.Title);
          tom.Update();
        }
      }
    }
  }
}

Basically, you only need to wrap the SPListItem object instead an HgListItem object. The HgListItem object is equipped with various useful methods and properties to help you work with an SPListItem object.

As demonstrated, HgListItem provides you some setter methods that allow you to assign values into the fields of the SPListItem object it contains.  With LiquidSilver, you just need to know what is the type of the field you want to use, not how to use it. And for each setter method, it will come with the getter method counterpart. For example, there are GetString(), GetDate(), and GetLookup() methods.

Currently, the getter/setter methods support the following field types, more will be added:

Field Type Getter Methods Setter Methods
Bool bool GetBool(Guid fieldId HgListItem SetBool(Guid fieldId, bool value)
Calculated string GetCalculated(Guid fieldId) HgListItem SetCalculated()
Date and Time DateTime GetDate(Guid fieldId) HgListItem SetDate(Guid fieldId, DateTime value)
Integer int GetInt(Guid fieldId) HgListItem SetInt(Guid fieldId, value)
Lookup SPFieldLookupValue GetLookup(Guid fieldId) HgListItem SetLookup(Guid fieldId, SPFieldLookupValue value)

HgListItem SetLookup(Guid fieldId, int lookupId, string lookupValue)

User and Group SPPrincipal GetPrincipal(Guid fieldId)

List<SPPrincipal> GetPrincipals(Guid fieldId)

string GetPrincipalsAsCsv(Guid fieldId)

HgListItem SetPrincipal(Guid fieldId, SPPrincipal principal)

HgListItem SetPrincipals(Guid fieldId, SPFieldUserValueCollection principals)

HgListItem SetPrincipalsFromCsv(Guid fieldId, string principalsAsCsv)

Text string GetString(Guid fieldId) HgListItem SetString(Guid fieldId, string value)
Integer SPFieldUrlValue GetUrl(Guid fieldId) HgListITem SetUrl(Guid fieldId, string url, string description)

HgListITem SetUrl(Guid fieldId, Uri url, string description)

All field setter/getter methods can identify the field by the field ID (GUID) or the field internal name or display name — in that order.

If you have noticed in the example also, you will see that HgListItem also exposes a property called Title, which corresponds with the Title property of the SPListItem object. In SPListItem, this property is read-only, but in HgListItem, you can also update it. There are also some other similar properties as follow:

Property Type Access Corresponding SPListItem Field
ID int read-only ID
UniqueId Guid read-only UniqueId
Title string read-write Title
Author SPUser read-write Author
Editor SPUser read-write Editor
CreatedOn DateTime read-only Created
ModifiedOn DateTime read-only Modified

I hope this will help you get started with LiquidSilver. Please keep an eye for future posts exploring the goodies of LiquidSilver.