Fun With Extension Method and Fluent Interface

April 13, 2010 07:01 by Anton

Since C# 3.0, object initializer has been my favourite.

Given the following class:

public class Book
{
    public string Isbn {get;set;}
    public string Title {get; set;}
    public string Author {get; set;}
    public int TotalPages {get;set;}
    public void Save()
    {
	//some persistent logic
    }
}

Prior to C# 3.0 you’ll normally use the following codes:

Book book=new Book();
book.Isbn="1284848395";
book.Title="What the hell?";
book.Author="Unknown";
book.TotalPages=40;
book.Save();

Tiresome, right? Consider the following statement:

new Book{
    Isbn="1284848395", Title="What the hell?",
    Author="Unknown",TotalPages=40
}.Save();

We get the same result with only 1 statement. Now what happened if your variable is not initialized directly, but taken from other method, let’s say getter or perhaps factory method. You’ll still need to code with old style. What if you are a fluent interface lover so you want 1 statement only.

We can use this.

public static T Do<T>(this T o,Action<T> action)
{
    action(o);
    return o;
}

Notice how we call it:

GetBook().Do<Book>(b=>{
   b.Isbn="1284848395"; b.Title="What the hell?"; 
   b.Author="Unknown";b.TotalPages=40;        
}).Save();

It is certainly more verbose, but if 1 statement is what you’re after then it works. You can also refactor anonymous method into a concrete method since it will make code cleaner.


Compare Objects Based On Their Properties

April 12, 2010 04:21 by Anton

When we do testing, we often need to compare 2 objects. The problems are:

  • It is often that we don’t bother to override GetHashCode and Equals method. Laziness plays part here :) .

  • We often need to ignore some properties.

  • There are properties that need special comparison method.

  • They are different types, but have similar set of properties. The worst case is you are comparing against anonymous /upcasted object.

Once again, reflection solves the problem easily for us.

bool AreEqual(object obj1, object obj2, ICollection<string> lstException, 
IDictionary<string, Func<object, object, bool>> methodDictionary)
{
    var type1 = obj1.GetType();
    var arrProperty = type1.GetProperties();
    foreach (var property in arrProperty)
    {
        if (lstException != null && lstException.Contains(property.Name))
            continue;
        var value1 = property.GetValue(obj1, null);
        var value2 = property.GetValue(obj2, null);
        if ((value1 == null && value2 != null) || (value1 != null && value2 == null))
            return false;
        if (value1 == null) continue;
        if (methodDictionary == null || !methodDictionary.ContainsKey(property.Name))
        {
            if (!value1.Equals(value2))
                return false;       
        }
        else
        {
            var method = methodDictionary[property.Name];
            if (method != null)
                return method(value1, value2);
            return false;
        }
    }
    return true;
}

Example of usage:

void TestCompare()
{
    var object1 =
        new {Isbn = 10203299399, Name = "Book One", Price = 300, 
Author = new {ID = 123, Name = "Gray"}};
    var object2 =
        new {Isbn = 10203299399, Name = "Book One", Price = 230, 
Author = new {ID = 123, Name = "Gray"}};
    var result=AreEqual(object1, object2, new List<string> {"Price"},
new Dictionary<string, Func<object, object, bool>>
       {
            {"Author",(obj1,obj2)=>object1.Author.ID==object2.Author.ID}
       });
    Console.WriteLine(result.ToString());
}

In the above method, we compare 2 anonymous objects, ignore Price property, and compare Author property based on their ID.

I often call this method inside nUnit’s Assert.IsTrue .


Firing Events Anywhere With Event Aggregator

January 7, 2010 07:41 by Anton

If you create a windows client application, you’ll often need to fire an event from one window / form to others.  We can do it easily by creating an event aggregator, which receives event notifications and process them by their name.

 

public delegate void CommonHandler(object data);

public sealed class EventAggregator
{
    public static object locker = new object();
    public static EventAggregator instance = null;
    private Dictionary<string, List<CommonHandler>> dicEvent = null;

    private EventAggregator()
    {
        dicEvent = new Dictionary<string, List<CommonHandler>>();
    }

    public static EventAggregator GetInstance()
    {
        if (instance == null)
        {
            lock (locker)
            {
                if (instance == null)
                {
                    instance = new EventAggregator();
                }
            }
        }
        return instance;
    }

    public void Subscribe(string eventName, CommonHandler handler)
    {
        lock (locker)
        {
            if (!dicEvent.ContainsKey(eventName))
                dicEvent[eventName] = new List<CommonHandler>();
            if (!dicEvent[eventName].Contains(handler))
                dicEvent[eventName].Add(handler);
        }
    }

    public void Publish(string eventName, object data)
    {
        lock (locker)
        {
            if (dicEvent.ContainsKey(eventName))
            {
                for (int i = 0; i < dicEvent[eventName].Count; i++)
                {
                    if (dicEvent[eventName][i] != null)
                        dicEvent[eventName][i](data);
                }

            }
        }
    }

    public void Unsubscribe(string eventName, CommonHandler handler)
    {
        lock (locker)
        {
            if (dicEvent.ContainsKey(eventName))
            {
                int index = dicEvent[eventName].IndexOf(handler);
                if (index > -1)
                    dicEvent[eventName].RemoveAt(index);
                if (dicEvent[eventName].Count == 0)
                    dicEvent.Remove(eventName);
            }
        }
    }
}

The implementation above is  singleton class but you may change it into static class if you don’t wish to add other instance class behavior (such as indexer, implements interface,etc). You may also change the delegate definition to suit your need.

The source code (along with example) is available here


Localizing Enum Description

December 18, 2009 08:26 by Anton

Recently, I ran into a problem , where I need to iterate through an enum, and get a localized description of its member. As an example, I’ll use enum Faculties.

public enum Faculties
{
    Engineeering=1,
    Economy=2,
    Physchology=3,
    Law=4,
    Pharmacy=5
}

Since we’re doing localization we need to create resx file and localized resx (in this example I use Indonesian culture), and assign value for each enum member. Don’t forget to set resource access modifier to public.

enum_neutral

enum_localized

How do we connect enum member with resource file? We can use a DescriptionAttribute and add it to all enum members. The trick here is we set the description to strongly type property name .

So here is our final enum:

public enum Faculties
{
    [Description("Faculties_Engineering")]
    Engineering = 1,

    [Description("Faculties_Economy")]
    Economy = 2,
        
    [Description("Faculties_Physchology")]
    Physchology = 3,
        
    [Description("Faculties_Law")]
    Law = 4,
        
    [Description("Faculties_Pharmacy")]
    Pharmacy = 5
}

And finally we add extension method for Faculties enum

public static class Extensions
{
    public static string ToLocalizedString(this Faculties val)
    {
         DescriptionAttribute[] attributes = (DescriptionAttribute[])val.GetType().GetField(val.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
         string description = attributes.Length > 0 ? attributes[0].Description : string.Empty;
         string result = string.Empty;
         if (!string.IsNullOrEmpty(description))
         {
             result = typeof(LanguageResource).GetProperty(description).GetValue(null, null) as string;
         }
         return result;
    }
} 

Here is the output of iterating Faculties enum in Indonesian culture:

console_enum

LocalizedEnum.7z (7.12 kb)


Reducing Working Set With EmptyWorkingSet

December 7, 2009 04:14 by Anton

If you develop a desktop based application, you’ll notice that the working set size is quite big. For an empty windows form application, the size can be around 20 MB.

While this is not a problem, sometimes you may want to ‘trick’ the user that your running application has low memory consumption. By using P/Invoke this is possible.

 


[DllImport("psapi.dll")]
static extern int EmptyWorkingSet(IntPtr hwProc);

static void ClearMemory()
{
	  try
      {
            EmptyWorkingSet(Process.GetCurrentProcess().Handle);
      }
      catch
      {
      }
}

 

I got this information from this article. You need to remember that this method will only affect the working set, not the private bytes.