December 10, 2014

Extremely Helpful Extension Methods in C#

Developers consumed lots of time before C# 3.0 to write methods but after C# 3.0, Microsoft introduces the terminology called "Extension Method" that is saving lots of developer time. Now they have to called these methods to done the matters quickly.

As per Microsoft's correspondence, Extension Methods allow you to create new functionality for existing types without modifying the actual type itself. Extension methods should contains these attributes: 

a. The class has to be static.
b. The method has to be static.
c. The method's first parameter in the signature must have the "this" declared.

You can create your own extension methods which will helps you throughout project and you can easily return the desire result by passing the method name. 

Under below are list of powerful extension methods that will save your lots of development time.

As per rule (a), class has to be static so create static class and then place all the custom extension methods there; I created the custom Extension Method class as:


public static class CustomExtensionMethods
{

}

As per rule (b, c), following custom extension method can reduce lots of your development time efforts.

1. Calculate Age:
    To calculate how old someone is:


public static int CalculateAge(this DateTime dateTime)
{
    var age = DateTime.Now.Year - dateTime.Year;

    if (DateTime.Now < dateTime.AddYears(age))
    {
        age--;
    }

    return age;
}

2. Has<T>()/Is<T>()/Add<T>()/Remove<T>()
   When you required an enumerated type are like flags instead of full items then use the following method:


public static bool Has<T>(this System.Enum type, T value)
{
    try
    {
        return (((int)(object)type & (int)(object)value) == (int)(object)value);
    }
    catch
    {
        return false;
    }
}

public static bool Is<T>(this System.Enum type, T value)
{
    try
    {
        return (int)(object)type == (int)(object)value;
    }
    catch
    {
        return false;
    }
}

public static T Add<T>(this System.Enum type, T value)
{
    try
    {
        return (T)(object)(((int)(object)type | (int)(object)value));
    }
    catch (Exception ex)
    {
        throw new ArgumentException(
            string.Format("Could not append value from enumerated type '{0}'.",
                typeof(T).Name), ex);
    }
}

public static T Remove<T>(this System.Enum type, T value)
{
    try
    {
        return (T)(object)(((int)(object)type & ~(int)(object)value));
    }
    catch (Exception ex)
    {
        throw new ArgumentException(
            string.Format("Could not remove value from enumerated type '{0}'.",
                typeof(T).Name), ex);
    }
}

3. ToReadableTime()
   This method is useful when you required to display a message like 'One second ago'.


public static string ToReadableTime(this DateTime value)
{
    var timeSpan = new TimeSpan(DateTime.UtcNow.Ticks - value.Ticks);
    double totalSecond = timeSpan.TotalSeconds;

    if (totalSecond < 60)
    {
        return timeSpan.Seconds == 1 ? "one second ago" : timeSpan.Seconds + " seconds ago";
    }

    if (totalSecond < 120)
    {
        return "a minute ago";
    }

    if (totalSecond < 2700) // 45 * 60
    {
        return timeSpan.Minutes + " minutes ago";
    }

    if (totalSecond < 5400) // 90 * 60
    {
        return "an hour ago";
    }

    if (totalSecond < 86400) // 24 * 60 * 60
    {
        return timeSpan.Hours + " hours ago";
    }

    if (totalSecond < 172800) // 48 * 60 * 60
    {
        return "yesterday";
    }

    if (totalSecond < 2592000) // 30 * 24 * 60 * 60
    {
        return timeSpan.Days + " days ago";
    }

    if (totalSecond < 31104000) // 12 * 30 * 24 * 60 * 60
    {
        int months = Convert.ToInt32(Math.Floor((double)timeSpan.Days / 30));
        return months <= 1 ? "one month ago" : months + " months ago";
    }

    var years = Convert.ToInt32(Math.Floor((double)timeSpan.Days / 365));
    return years <= 1 ? "one year ago" : years + " years ago";
}

4. WorkingDay()/IsWeekend()/NextWorkday()
   When you want to display like 'Today is working day, weekend or determine the next working day' then:


public static bool WorkingDay(this DateTime date)
{
    return date.DayOfWeek != DayOfWeek.Saturday && date.DayOfWeek != DayOfWeek.Sunday;
}

public static bool IsWeekend(this DateTime date)
{
    return date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
}

public static DateTime NextWorkday(this DateTime date)
{
    var nextDay = date;

    while (!nextDay.WorkingDay())
    {
        nextDay = nextDay.AddDays(1);
    }

    return nextDay;
}

5. Next()
   Determine the Next date by passing in a DayOfWeek (i.e. From this date, when is the next Tuesday?)


public static DateTime Next(this DateTime current, DayOfWeek dayOfWeek) 
{ 
    int offsetDays = dayOfWeek - current.DayOfWeek; 

    if (offsetDays <= 0) 
    { 
       offsetDays += 7; 
    } 

    DateTime result = current.AddDays(offsetDays); 
    return result; 
}

6. str.ToStream()/stream.ToString()/CopyTo()
   If you want to take a large string and convert it to a Stream or vice-versa then use these:


public static Stream ToStream(this string str)
{
    byte[] byteArray = Encoding.UTF8.GetBytes(str);
    return new MemoryStream(byteArray);
}

public static string ToString(this Stream stream)
{
    var reader = new StreamReader(stream);
    return reader.ReadToEnd();
}

public static void CopyTo(this Stream fromStream, Stream toStream)
{
    if (fromStream == null)
    {
        throw new ArgumentNullException("fromStream");
    }

    if (toStream == null)
    {
        throw new ArgumentNullException("toStream");
    }
    
    var bytes = new byte[8092];
    int dataRead;

    while ((dataRead = fromStream.Read(bytes, 0, bytes.Length)) > 0)
    {
        toStream.Write(bytes, 0, dataRead);
    }
}

7. Between()   
   Check to see if a date is between two dates. 


public static bool Between(this DateTime dateTime, DateTime rangeStart, DateTime rangeEnd)
{
    return dateTime.Ticks >= rangeStart.Ticks && dateTime.Ticks <= rangeEnd.Ticks;
}

8.RemoveLast() / RemoveLastCharacter() / RemoveFirst() / RemoveFirstCharacter()
   These tricky method save lot of time in the heat of string manipulation. 


public static string RemoveLastCharacter(this String str)
{
    return str.Substring(0, str.Length - 1);
}

public static string RemoveLast(this String str, int number)
{
    return instr.Substring(0, instr.Length - number);
}

public static string RemoveFirstCharacter(this String instr)
{
    return str.Substring(1);
}

public static string RemoveFirst(this String str, int number)
{
    return str.Substring(number);
}

9. ToFileSize
   If you want to read the file of size then this method is easier to read the file size.


public static string ToFileSize(this long size)
{
    if (size < 1024) { return (size).ToString("F0") + " bytes"; }
    if (size < Math.Pow(1024, 2)) { return (size / 1024).ToString("F0") + "KB"; }
    if (size < Math.Pow(1024, 3)) { return (size / Math.Pow(1024, 2)).ToString("F0") + "MB"; }
    if (size < Math.Pow(1024, 4)) { return (size / Math.Pow(1024, 3)).ToString("F0") + "GB"; }
    if (size < Math.Pow(1024, 5)) { return (size / Math.Pow(1024, 4)).ToString("F0") + "TB"; }
    if (size < Math.Pow(1024, 6)) { return (size / Math.Pow(1024, 5)).ToString("F0") + "PB"; }

    return (size / Math.Pow(1024, 6)).ToString("F0") + "EB";
}

10. ToXmlDocument()/ToXDocument()
    This extension method is very handy and will save you a load of time when you need to convert an XmlDocument into an XDocument and vice-versa:


public static XmlDocument ToXmlDocument(this XDocument xDocument)
{
    var xmlDocument = new XmlDocument();

    using (var xmlReader = xDocument.CreateReader())
    {
        xmlDocument.Load(xmlReader);
    }

    return xmlDocument;
}

public static XDocument ToXDocument(this XmlDocument xmlDocument)
{
    using (var nodeReader = new XmlNodeReader(xmlDocument))
    {
        nodeReader.MoveToContent();
        return XDocument.Load(nodeReader);
    }
}

public static XmlDocument ToXmlDocument(this XElement xElement)
{
    var stringBuilder = new StringBuilder();
    var xmlWriterSettings = new XmlWriterSettings {OmitXmlDeclaration = true, Indent = false};

    using (var xmlWriter = XmlWriter.Create(stringBuilder, xmlWriterSettings))
    {
        xElement.WriteTo(xmlWriter);
    }

    var xmlDocument = new XmlDocument();
    xmlDocument.LoadXml(stringBuilder.ToString());
    return xmlDocument;
}

public static Stream ToMemoryStream(this XmlDocument xmlDocument)
{
    var memoryStream = new MemoryStream();
    xmlDocument.Save(memoryStream);
    memoryStream.Flush();//Adjust this if you want read your data 
    memoryStream.Position = 0;
    return memoryStream;
}

Hope these custom extension methods will helps you to reduce your development time and efforts. Stay tuned!