menu

Sunday, October 9, 2016

Sorting List by IComparable vs IComparer

List<T> class has a Sort() method which sorts the elements in the entire List<T> using the default comparer. (<T> => , ...)

List<string> strList = new List<string>();
strList.Add("Ss");
strList.Add("As");
strList.Add("Rs");
strList.Add("Ks");
strList.Sort();
foreach (string item in strList)
{
    Console.WriteLine(item);
}

IComparable - Sorting list of complex type like List<Employee> using IComparable and only by one way.

public class Employee
{
    public string Name { getset; }
    public int Age { getset; }
}

List<Employee> employee = new List<Employee>();
employee.Add(new Employee() { Name = "Ss", Age = 30 });
employee.Add(new Employee() { Name = "As", Age = 25 });
employee.Add(new Employee() { Name = "Rs", Age = 20 });
employee.Add(new Employee() { Name = "Ks", Age = 30 });
employee.Add(new Employee() { Name = "Av", Age = 50 });
employee.Sort();
foreach (Employee item in employee)
{
    Console.WriteLine("{0}, {1}", item.Name, item.Age);
}

So in order to do this we will have to implement Employee class by IComparable. and have to put sorting logic in implemented function CompareTo.

public class Employee : IComparable<Employee>
{
    public string Name { get; set; }
    public int Age { get; set; }
    public int CompareTo(Employee other)
    {
        if (this.Age == other.Age)
        {
            return this.Name.CompareTo(other.Name);
        }
        return this.Age.CompareTo(other.Age);
    }
}

IComparer - Used to sorting list of complex type using IComparer and by multiple ways like Name or by Age.

public class Employee
{
    public string Name { get; set; }
    public int Age { get; set; }
}
public class SortEmployeeByName : IComparer<Employee>
{
    public int Compare(Employee x, Employee y)
    {
        return string.Compare(x.Name, y.Name);
    }
}
public class SortEmployeeByAge : IComparer<Employee>
{
    public int Compare(Employee x, Employee y)
    {
        if (x.Age == x.Age)
        {
            return 0;
        }
        if (x.Age > y.Age)
        {
            return 1;
        }
        if (x.Age < y.Age)
        {
            return -1;
        }
        return 0;
    }
}

List<Employee> employee = new List<Employee>();
employee.Add(new Employee() { Name = "Ss", Age = 35 });
employee.Add(new Employee() { Name = "As", Age = 25 });
employee.Add(new Employee() { Name = "Rs", Age = 20 });
employee.Add(new Employee() { Name = "Ks", Age = 30 });
employee.Add(new Employee() { Name = "Av", Age = 50 });
//---------------
Console.WriteLine("By Name ....");
employee.Sort(new SortEmployeeByName());
foreach (Employee item in employee)
{
    Console.WriteLine("{0}, {1}", item.Name, item.Age);
}
//---------------
Console.WriteLine("By Age ....");
employee.Sort(new SortEmployeeByAge());
foreach (Employee item in employee)
{
    Console.WriteLine("{0}, {1}", item.Name, item.Age);
}



Signing - Strong vs Weak Reference

Prerequisite - Create 2 solution first one (Solution1) with 2 project (console - ConsoleApp and class library - CLApp) another (Solution2) with one project (class library - CLApp).
Create a class with same name (say MyClass) and function (say MyFun) in both class library and print message like "Test1" and "Test1" respectively. Now in Solution1 add the reference of class library to console app and inside main function call MyClass.MyFun(), build and copy ConsoleApp.exe and CLApp.dll in a new folder and run the ConsoleApp.exe and verify the output (Test1) on console.

Problem - Build Solution2 and copy the CLApp.dll to newly created folder and replace the old CLApp.dll of Solution1. Run the ConsoleApp.exe and verify the output (Test2) on console. The problem here is that ConsoleApp.exe is not strongly referenced with CLApp.dll and this is not safe at all because at anytime one who know about the class and function can change its internal logic and that will replace its behaviour. This is because of weak reference.

Solution - Go to property of class library project in Solution1 and sign in with a MyTest.snk file

and then refer it to console app (this will be a strong reference) and follow the same procedure of replacing the dll of Solution2 and run the app. This time it will throw exception saying that ...
Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly 'Signing-StrongAndWeakReferenceDLL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9498fd7f75415bf8' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT:0x80131040) at Signing_StrongAndWeakReference.Program.Main(String[] args)


Saturday, September 24, 2016

Code First CRUD in Entity Framework using ASP.NET

Steps to implement code first CRUD in entity framework. (Download Sample App)
1. Install entity framework liberary from NuGet.
2. Create model classes and context class
3. Create table to store student information and add connection string in Web.config file.
CREATE TABLE [dbo].[Students](
       [ID] [int] IDENTITY(1,1) NOT NULL,
       [Name] [nvarchar](max) NULL,
       [DOB] [datetime] NOT NULL,
       [Photo] [varbinary](max) NULL,
       [Height] [decimal](18, 2) NULL,
       [Weight] [real] NULL,
       CONSTRAINT [PK_Students] PRIMARY KEY CLUSTERED ([ID] ASC)
       WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
       IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
       ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
4. Create UI in Asp.net WebForm as shown above. (Download .aspx and aspx.cs)
5. Create a handler to bind binary data to grid view. (Download handler code)

Sunday, September 18, 2016

Covariance & Contravariance

Covariance 
Before .Net 4.0 it was not possible to assign a reference variable of List of parent type to List of its child type.
IEnumerable<Employee> empList = new List<PermanentEmployee>(); X (not possible)
Where PermanentEmployee is child type of Employee type.

But possible in 4.0 on-words by introducing out keyword.

Contravariance
A base type of function pointer (delegate) reference variable was not able to get assign to reference variable of its child type.
delegate void MyPtr<T>(T o);
MyPtr<Employee> oEmp = Print;
MyPtr<PermanentEmployee> oPEmp = oEmp; X (not possible)

But possible in 4.0 on-words by introducing in keyword.
delegate void MyPtr<in T>(T o);

Below is the complete code demonstrating both.
using System;
using System.Collections.Generic;
namespace CovarianceContravariance
{
    class Program
    {
        delegate void MyPtr<in T>(T o);
        static public void Contraveriance()
        {
            MyPtr<Employee> oEmp = Print;
            MyPtr<PermanentEmployee> oPEmp = oEmp; //Backword campatability
        }
        static void Print(Employee emp)
        {
            Console.WriteLine(emp.Name);
        }
        //-------------------------------------------------------------
        public void Coveriance()
        {
            Employee emp = new PermanentEmployee(); //Polymorphism - Valid Statement
            emp = new ContractEmployee(); //Polymorphism - Valid Statement
            //Valid Statement, Invalid below 4.0
            IEnumerable<Employee> empList = new List<PermanentEmployee>();
        }
        //-------------------------------------------------------------
        static void Main(string[] args)
        {
           
        }
    }
    public class Employee
    {
        public string Name = "Animal";
    }
    public class PermanentEmployee : Employee
    {

    }
    public class ContractEmployee : Employee
    {

    }
}

Data Annotation

Is a way to validate business objects in easy and simplified manner.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace DataAnnotations
{
    class Program
    {
        static void Main(string[] args)
        {
            Customer cust = new Customer();
            try
            {
                cust.name = "";//It will throw exception
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            cust.name = "TestName";
            cust.number = "1234567890";//here length is 11 and requird max length is 10
            ValidationContext context = new ValidationContext(cust);
            List<ValidationResult> vResults = new List<ValidationResult>();
            bool isValid = Validator.TryValidateObject(cust, context, vResults, true);
            foreach (ValidationResult vResult in vResults)
           {
                Console.WriteLine(vResult.ErrorMessage);
            }
            Console.WriteLine("Customer Validation: {0}", isValid);
        }
    }
    public class Customer
    {
        private string _name;
        //Traditional way
        public string name
        {
            get { return _name; }
            set
            {
                if (value.Length == 0)
                {
                    throw new Exception("Name is required !");
                }
                _name = value;
            }
        }
        private string _number;
        //Through data annotation
        [Required(ErrorMessage = "Number is required !")]
        [StringLength(10, ErrorMessage = "Length should be <= 10")]
        public string number
        {
            get { return _number; }
            set { _number = value; }
        }
    }
}