Thursday, 24 July 2014

Export to CSV from a List of class object(s).

Export to CSV from a List of class object(s).

Today I got an assignment to transfer/export data into CSV file from a List of class object so I thought to make it generic so that I can use it in multiple modules and projects too, but how with the following challenges?

 Exclude Class Property.
  Custom Header.
   No Header.
  Column Order while exporting to CSV.
  Should be Generic.
The solution came to mind is to use C# Attribute to handle the challenges.

Attribute (MSDN):Attributes provide a powerful method of associating metadata, or declarative information, with code (assemblies, types, methods, properties, and so forth).

Reflection (MSDN): Reflection provides objects (of type Type) that describe assemblies, modules and types. You can use reflection to dynamically create an instance of a type, bind the type to an existing object, or get the type from an existing object and invoke its methods or access its fields and properties. If you are using attributes in your code, reflection enables you to access them. Using reflection I can extract the property information or custom attribute provided for CSV.

Generics (MSDN):Generics introduce to the .NET Framework the concept of type parameters, which make it possible to design classes and methods that defer the specification of one or more types until the class or method is declared and instantiated by client code.Generics used to export any List of class object without re-writing code again and again.
Let’s start with designing Attribute.

using System;
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class CSVAttribute : Attribute
{
    private readonly bool allowExport;
    private readonly int order;
    private readonly string columnHeader;
    private readonly string format;
 
    public CSVAttribute(bool allowExport = falseint order = 0
                        string columnHeader = "")
    {
        this.allowExport = allowExport;
        this.order = order;
        this.columnHeader = columnHeader;
    }
 
    public CSVAttribute(bool allowExport = falsestring columnHeader = ""
                        int order = 0string format = "")
    {
        this.allowExport = allowExport;
        this.order = order;
        this.columnHeader = columnHeader;
        this.format = format;
    }
 
    public string ColumnHeader
    {
        get { return columnHeader; }
    }
 
    public bool AllowExport
    {
        get { return allowExport; }
    }
 
    public int Order
    {
        get { return order; }
    }
 
    public string Format
    {
        get { return format; }
    }
}

So we have defined CSVAttribute which will be applied at property level, multiple definitions on same property is not allowed and it is not inherited.
This attribute has constructor which take three values

1.   AllowExport (whether you want to export to CSV default is false).
2.   ColumnHeader (Column Header you want to write while exporting).
3.   Order (Order in which you want column to be printed).

Let’s now define the Custom CSVPropertyInfo Class which we will use during export to CSV option.

     using System.Reflection; 
    public class CSVPropertyInfo
    {
        public PropertyInfo Property { getset; }
        public CSVAttribute Attribute { getset; }
    }

Now time to define the CSVFileWriter class who is responsible for writing the header and data in CSV for provided property or propertied only.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
public class CSVFileWriter<T> : ICSVFileWriter<Twhere T : class
    {
        private List<T> Data { getset; }
 
        private IEnumerable<CSVPropertyInfo> ExportProperties { getset; }
 
        private string Headers
        {
            get
            {
                var headerName = new StringBuilder();
                foreach (CSVPropertyInfo property in ExportProperties)
                {
                    headerName.Append(string.Format("\"{0}\","
                    property.Attribute.ColumnHeader));
                }
                headerName.Remove(headerName.Length - 11);
                return headerName.ToString();
            }
        }
 
        public void Write(string fullFileName, List<T> data, bool writeHeader = true)
        {
            if (data == null || !data.Any())
            {
                throw new Exception("Please provide the data");
            }
            Data = data;
 
            SetExportProperties();
 
            var fileData = new StringBuilder();
            if (writeHeader)
            {
                fileData.AppendLine(Headers);
            }
 
            fileData.Append(GetRowData());
            WriteFile(fullFileName, fileData.ToString());
        }
 
        private void SetExportProperties()
        {
            var properties = new List<CSVPropertyInfo>();
            foreach (PropertyInfo property in Data.First().GetType().GetProperties())
            {
                object[] attrs = property.GetCustomAttributes(true);
                foreach (CSVAttribute attr in attrs
                         .Where(x => x.GetType() == typeof(CSVAttribute)))
                {
                    if (attr != null && attr.AllowExport)
                    {
                        properties.Add(new CSVPropertyInfo { 
                              Attribute = attr, 
                              Property = property });
                    }
                }
            }
            ExportProperties =
            properties.OrderBy(x => x.Attribute.Order).ToList();
        }
 
        private string GetRowData()
        {
            var sb = new StringBuilder();
            foreach (T data in Data)
            {
                var row = new StringBuilder();
                foreach (var property in ExportProperties)
                {
                    if (property.Attribute.Format.Length > 0)
                    {
                        var propType = property.Property.PropertyType;
                        if (propType == typeof(DateTime))
                        {
                            row.Append(string.Format("\"{0}\","
                            Convert.ToDateTime(property.Property.GetValue(data, null))
                            .ToString(property.Attribute.Format)));
                        }
                        else if (propType == typeof(double|| propType == typeof(float))
                        {
                            row.Append(string.Format("\"{0}\","
                            Convert.ToDouble(property.Property.GetValue(data, null))
                            .ToString(property.Attribute.Format)));
                        }
                        else
                        {
                            row.Append(string.Format("\"{0}\","
                            Convert.ToDouble(property.Property.GetValue(data, null))));
                        }
 
                    }
                    else
                    {
                        row.Append(string.Format("\"{0}\","
                        Convert.ToString(property.Property.GetValue(data, null))));
                    }
                }
                row.Remove(row.Length - 11);
                sb.AppendLine(row.ToString());
            }
            return sb.ToString();
        }
 
        private void WriteFile(string fullFileName, string data)
        {
            using (var streamWriter = new StreamWriter(fullFileName, false))
            {
                streamWriter.Write(data);
                streamWriter.Close();
            }
        }
    }
 
    public interface ICSVFileWriter<Twhere T : class
    {
        void Write(string fullFileName, List<T> data, bool writeHeader = true);
    }

So our CSV writer is ready now to get export we need to implement attribute in our class.
For example we have Employee class as follow.
publicclassEmployee
{
    [CSV(true, "Date of Birth", 3)]
    publicDateTime DOB { get; set; }

    [CSV(true, "First Name",1)]
    publicstringFirstName { get; set; }

    [CSV(true, "Last Name", 2)]
    publicstringLastName { get; set; }

    publicstringUserId { get; set; }
}

Once the attributeis defines it is ready for export. In above class we have not places CSV attribute on UserId so this field will not be considered while exporting data. The order for column we have defined which is different than the property order in class. The Second parameter in CSV is Column Header for DOB property we will use column Header as a Date of Birth. Now let’s execute the actual export.

varemployeeList = newList<Employee>
                        {
newEmployee
                                {
                                    DOB = DateTime.Now.AddDays(-365*28),
FirstName = "K",
LastName = "P"
                                },
newEmployee
                                {
                                    DOB = DateTime.Now.AddDays(-365*28),
FirstName = "P",
LastName = "D"
                                },
newEmployee
                                {
                                    DOB = DateTime.Now.AddDays(-365*29),
FirstName = "M",
LastName = "G"
                                }
                        };

varcsvFileWriter = newCSVFileWriter<Employee>();
csvFileWriter.Write("c:\\Test\\Employee.csv", employeeList);

Happy Coding.J

Monday, 2 September 2013

What is MVC?

In technology world MVC stands for Model View Controller; MVC is an architectural design pattern to develop the software. MVC design pattern is widely used to develop a web application.

Model: Model represents the real life entity such as customer. Model consists of application data, business rules, logic and functions.

View: View represents the model data on UI or page (web application). View is actual representation of data in user friendly format. View present data in terms of user controls, charts, diagrams etc.

Controller: Controller is mediator between Model and View. It takes model data and represents it on the view. It could also take input from the user and send to the model for further processing or to take action on it by model.

This design pattern is exists since 1970. The MVC pattern is widely used with programming languages such as Java, Smalltalk, C, and C++. Now Microsoft Web Developer can easily integrate this design pattern with Asp.Net application using RAZOR or ASPX engine.


Now next question comes into your mind is that why should I use MVC or what are the advantages of using the MVC design pattern?

Following are the advantages of using MVC pattern

  • Separation of concerns: View is only responsible for displaying data on UI. No business logic is tightly integrated in view. Controller is responsible for processing user requests. Business logic now resides in a model.
  • Unit Testing:  You can test your business logic using Unit test tools such as NUnit, xUnit etc.
  • TDD: TDD stands for Test Driven Development, In TDD approach developer will always writes test first for a module or business logic. This approach is helpful in early detection of an issue in development.         



Tuesday, 9 July 2013

Generic Cache Manager


To improve the performance of an application many a times we need to cache frequently used data. This generic cache manager will help to maintain cache using concurrent dictionary (Key, Value Pair). Concurrent Dictionary represents a thread-safe collection of key/value pairs that can be accessed by multiple threads concurrently.

Generic cache manager allows you to add, delete and retrieve data from the concurrent dictionary.

If you are using dependency injection or container like Unity, Windsor-Castle etc. in your application then you have to register cache manager as a Singleton. Otherwise you can achieve a singleton pattern by making CacheManager class and its method as a static. Following is the generic Cache Manager code.

    using System;

    public interface ICacheManager
    {
        /// <summary>
        /// Add a new object into the cache
        /// </summary>
        /// <param name="key">The key of the object to add</param>
        /// <param name="value">The value of the object to add</param>
        void Add(string key, object value);

        /// <summary>
        /// Check whether the key is contained by the cache
        /// </summary>
        /// <param name="key">The key to check</param>
        /// <returns>Returns true if the key is contained by the cache</returns>
        bool Contains(string key);

        /// <summary>
        /// Returns the number of items in the cache
        /// </summary>
        /// <returns></returns>
        int Count();

        /// <summary>
        /// Get the object that its key is given
        /// </summary>
        /// <typeparam name="T">The object</typeparam>
        /// <param name="key">The given key to check</param>
        /// <returns>returns the object or null if it doesn't exists</returns>
        T Get<T>(string key);

        /// <summary>
        /// Get the object that its key is given
        /// </summary>
        /// <typeparam name="T">The object</typeparam>
        /// <param name="key">The given key to check</param>
        /// <param name="getData">Function that retrieves the data </param>
        /// <returns>returns the object or null if it doesn't exists</returns>
        T SafeGet<T>(string key, Func<T> getData);

        /// <summary>
        /// Removes the object that is referenced by the given key
        /// </summary>
        /// <param name="key">The given key</param>
        bool Remove(string key);
    }




    using System;
    using System.Collections.Concurrent;


    public class CacheManager : ICacheManager
    {
        private readonly ConcurrentDictionary<string, object> cache;

        public CacheManager()
        {
            cache = new ConcurrentDictionary<string, object>();
        }

        public void Add(string key, object value)
        {
            cache.AddOrUpdate(key, value, (newKey, newValue) => value);
        }

        public bool Contains(string key)
        {
            return cache.ContainsKey(key);
        }

        public int Count()
        {
            return cache.Count;
        }

        public T Get<T>(string key)
        {
            return cache.ContainsKey(key) ? (T) cache[key] : default(T);
        }

        public T SafeGet<T>(string key, Func<T> getData)
        {
            return (T) cache.GetOrAdd(key, x => getData());
        }

        public bool Remove(string key)
        {
            object output;
            return cache.TryRemove(key, out output);
        }
    }


Example: 

How to add objects or data into the cache.

cacheManager.Add(<<key>>, <<data>>);

How to get data from the cache.

var cacheData = _cacheManager.Get<T>(<<key>>);

Wednesday, 8 May 2013

What is Action,Func delegate in C#

Action: 

Encapsulates a method that has no parameter or one parameter or more parameters and does not return a value, method return type should be void(c#) or Sub .... End Sub (vb.net).

E.g.

    class Program
    {


        static void Main(string[] args)
        {
            Action<int> action = new Action<int>(DoSomething);
            action.Invoke(1009);
        }

        static void DoSomething(int i)
        {
            Console.WriteLine(i);
        } 
    }

O/P:
1009

Func:

Encapsulates a method that has no parameters or one or parameters and returns a value of the type specified by the TResult parameter.

//Func delegate with one parameter and TResult

public delegate TResult Func<in T, out TResult>(T arg)

E.g.
   class Program
    {
        private static void Main(string[] args)
        {            
            Func<int, double> func = new Func<int, double>(CalcualteSomething);
            Console.WriteLine(func(5)); //Should Print 25
        }
  
        private static double CalcualteSomething(int i)
        {      
           return (double) i*2;
        }
    } 


Tuesday, 7 May 2013

WPF Architecture


The Major components of WPF Architecture are Presentation Framework, Presentation Core and Media Integration Layer. The architecture divides in three major groups Managed Layer, Media Integration Layer (Unmanaged code) and Core Operating System.

Managed layer contains WindowsBase, Presentation Framework and Presentation Core assembly. Media Integration Layer contains Milcore(Media Integration Library Core)  and WindowsCodecs modules and both are unmanaged code. Media Integration Layer interacts with Direct3D and Direct3D interacts with Device Driver.


Managed Layer

Presentation Framework – Holds top level WPF types includes Window, Controls, Styles, and Layout Panels etc. The code and controls written in WPF Application is mostly interacting with this layer.

Presentation Core – Holds base types such as UI Element and Visual. Almost all the controls you are directly interacting with are derived from these types. Presentation Framework uses most of the types defined in this layer.

WindowBase: They hold even more basic elements which are capable of being used outside the WPF environment like Dispatcher.

Unmanaged Layer(milcore.dll) 

MilCore –
 Media Integration Library is core rendering system. MIL is unmanaged code. This layer converts WPF elements into the format that Direct3D expects. Windows7 & Windows Vista use this assembly to render its Desktop.

WindowsCodecs– This is low level API which gives imaging support in WPF applications. Provides supports for imaging like image processing, image displaying and scaling etc.


Direct3D – This layer is used to render graphics created using WPF Applications.

User32:- This provides the windows look and feel for buttons and textboxes and other UI elements. User32 lacked drawing capabilities.

GDI (Graphics device interface):- Microsoft introduced GDI to provide drawing capabilities. GDI not only provided drawing capabilities but also provided a high level of abstraction on the hardware display. In other words it encapsulates all complexities of hardware in the GDI API.

GDI+:- GDI+ was introduced which basically extends GDI and provides extra functionalities like jpg and PNG support, gradient shading and anti-aliasing. The biggest issue with GDI API was it did not use hardware acceleration and did not have animation and 3D support.

Custome Service Class to connect wcf service

  using  System; using  System.ServiceModel; namespace Custom.Service.Client {      // Borrowed from: http://old.iserviceoriented.com/blog/p...