Next step of programming

Just another WordPress.com weblog

Archive for the ‘General’ Category

Convert ILIST, LIST to DataSet with child tables and relations

with 6 comments

There was requirement to convert ILIST or LIST to DataSet so that it can be assigned to some of the controls like Grid or DevExpress Grid. For that i have written following class to convert from LIST or ILIST to DataSet

  • Converts only ILIST and LIST
  • Convert sub lists to another table which will be related to the parent list
  • Creates Relation between tables
  • Works only on the properties not on fields. You can easily modify it for that

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;

namespace TowardsNext
{
public static class ListConvertor    
{
public static DataSet ConvertToDataSet<T>(IList list)
{
DataSet dataSet = new DataSet();

CreateDataSet(dataSet, typeof(T), false);
FillDataSet(typeof(T), list.ToList(), dataSet, -1);
CreateRelations(dataSet, typeof(T), null);

return dataSet;
}

/// 
/// Create the structure for all the tables in the data set        
/// 
/// Data set in which tables will be created
/// Type of which dataset has to be created
/// Whether current type is a child table        
private static void CreateDataSet(DataSet dataSet, Type type, bool isChildTable)
{
DataTable dataTable = new DataTable(type.Name);

//Create the ID columns for having relation in the tables 
            dataTable.Columns.Add(new DataColumn("ID", typeof(int)));
if (isChildTable)
{
dataTable.Columns.Add(new DataColumn("ParentID", typeof(int)));
}

// Create the structure for the data tables to be
// added in the the data set            
foreach (PropertyInfo pInfo in type.GetProperties())
{
if (pInfo.PropertyType.IsGenericType &&
(pInfo.PropertyType.GetGenericTypeDefinition() == typeof(List<>)
|| pInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)))
{
// If associate lists are there make then another table
                    CreateDataSet(dataSet,
pInfo.PropertyType.GetGenericArguments()[0],
true);
}
else                
{
dataTable.Columns.Add(new DataColumn(pInfo.Name, pInfo.PropertyType));
}
}

//Add the table to the dataset
            dataSet.Tables.Add(dataTable);
}

/// 
/// Fill all the tables of data set with data in the respective list        
/// 
/// Type of which datatable is to be filled
/// List of data
/// Data Set in which data tables will be filled with data
/// ID of parent record. If -1 one then no parent        
private static void FillDataSet(Type type, IList list, DataSet dataSet, int parentID)
{
PropertyInfo[] propertyInfos = type.GetProperties();
DataTable dataTable = dataSet.Tables[type.Name];
int id = dataTable.Rows.Count + 1;

foreach (object item in list)
{
DataRow row = dataTable.NewRow();

// Set new id and related parent id
                row["ID"] = id;
if (parentID != -1)
row["ParentID"] = parentID;

// Load all the data from the properties of the type
// and save them into the datatable                
foreach (PropertyInfo info in propertyInfos)
{
if (info.PropertyType.IsGenericType &&
(info.PropertyType.GetGenericTypeDefinition() == typeof(List<>)
|| info.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)))
{
IList subList = (IList)info.GetValue(item, null);
if (subList != null && subList.Count > 0)
{
FillDataSet(subList[0].GetType(),
subList,
dataSet, id);
}
}
else                    
{
row[info.Name] = info.GetValue(item, null);
}
}

dataTable.Rows.Add(row);
id++;
}
}

/// 
/// Creates the relation between the tables according to the         
/// type and parent table on field ID and ParentID        
/// 
/// Data set containing parent and child table
/// Type of the list
/// Parent table to which relations has to be done        
private static void CreateRelations(DataSet dataSet, Type type, DataTable parentTable)
{
DataTable dataTable = dataSet.Tables[type.Name];

// If parent table exsits then create relation
// with child table on field Parent ID            
if (parentTable != null)
{
dataSet.Relations.Add(
new DataRelation(parentTable.TableName + "_ID_"
                        + "PARENTID_" + dataTable.TableName,
parentTable.Columns["ID"],
dataTable.Columns["ParentID"]));
}

// Check for other lists under current object
// go for another relation if exists            
foreach (PropertyInfo pInfo in type.GetProperties())
{
if (pInfo.PropertyType.IsGenericType &&
(pInfo.PropertyType.GetGenericTypeDefinition() == typeof(List<>)
|| pInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)))
{
// If associate lists are there make then another table
                    CreateRelations(dataSet,
pInfo.PropertyType.GetGenericArguments()[0],
dataTable);
}
}
}
}
}


Tested with following code


;public class Student    
{
public string Name { get; set; }
public string Class { get; set; }
}

public class Teacher    
{
public string Name { get; set; }
public string Address { get; set; }
public List<Student> Students { get; set; }
}

class Program    
{
static void Main(string[] args)
{
List<Student> students = new List<Student>();
students.Add(new Student { Name = "Ram Prasad", Class = "LKG" });
students.Add(new Student { Name = "Dina Nath", Class = "Prep" });

List<Teacher> teachers = new List<Teacher>();
teachers.Add(
new Teacher{
Name="Om Prakash",
Address="Mangalore",
Students = students
});
teachers.Add(new Teacher                
{
Name = "Om Prakash 2",
Address = "Gurgaon",
Students = students
});

DataSet dataSet = ListConvertor.ConvertToDataSet<Teacher>(teachers);
}
}


It is not tested in all the cases and condition only checked with few cases and requirement. If any problem do reply, i will fix it up and re-post it. After converting we assigned it to devexpress grid and get the following successful output

Grid assigned to parent data table list with all child tables

Grid assigned to parent data table list with all child tables


Written by A.Sethi

April 16, 2009 at 11:20 am

Posted in General

Tagged with , , , ,

Named & Optional Parameter, C# 4.0 Part 2

with one comment

In visual basic we were having optional parameter option which can help you to send only some parameter to methods and reset will take the default values. Same feature is part of C# 4.0 where you can have default values for the parameters.

Optional Parameters & Their default values

Optional Parameters & Their default values


But one more noticeable feature is “named parameter”. You might have seen in VB also that if you want to set any of the parameter no values then you have to leave all other parameters also which are defined after that variable. To sort this out you can use named parameter which specify the name of the parameter and value for it “seats:4” where seats is the parameter and 4 is the value.

Named Parameters

Named Parameters


Both of the features are shown below in sample

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ParameterFeatures
{
class Program    
{
static void Main(string[] args)
{
Vehicle car = new Vehicle("V6");
Vehicle van = new Vehicle(seats:4);

Console.WriteLine("Engine : " + car.Engine);
Console.WriteLine("Seats : " + van.Seats.ToString());

Console.ReadLine();
}
}

class Vehicle    
{
public string Engine { get; set; }
public int Seats { get; set; }

public Vehicle(string engine = "V8", int seats = 5)
{
Engine = engine;
Seats = seats;
}
}
}

Written by A.Sethi

March 16, 2009 at 12:39 pm

Dynamic Lookup & dynamic Type, C# 4.0 Part 1

with one comment

C# 4.0 is out once again with new set of features. Now we will see one of the new feature of it, which is know as Dynamic Lookup. It is new approach for invoking thing more dynamically than before. It gives big freedom and working with various different kind of objects like COM etc will be too easy.

Big question how. I have written one sample below where i am grabbing the object of excel instance which is already running and filling data in it. In the previous version of C# we used to do it with the help of InvokeMember funtions of the object. But in C# 4.0 story is differentM

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DynamicObjects
{
class Program    
{
static void Main(string[] args)
{
dynamic excel = System.Runtime.
InteropServices.Marshal.GetActiveObject("Excel.Application");

//Display the name of the work book            
Console.WriteLine(excel.ActiveWorkbook.Name);

//Select the range and place some data here
excel.Range("B2").Select();
excel.ActiveCell.FormulaR1C1 = "Sample Data";

//Wait for the input            
Console.ReadLine();
}
}
}


It was so simple to use the dynamic object, That i have to just type out the properties and method in the front of dynamic object. At the time of getting that object it will be handled automatically and will map the functions and methods. Its really a great feature, which can save time and give more freedom to the developer.

Difference between VAR & DYNAMIC

VAR It is also know as local type inference feature of C#. This feature will allow you to remove the data type from the left hand side and create the type on the fly. But still you have to specify the type in the right hand side and var will be replaced by the new type which will be built at compile time.

DYNAMIC it is step ahead of the VAR. It will get the information of the object not at the compile time rather at the time of creation of that object. It is done at runtime only.

Written by A.Sethi

March 16, 2009 at 11:27 am

Posted in General

Tagged with , , ,

XML Serialization

without comments

Some time we need to save the data in the files which is nothing but the details of the object. For example i am having a application doing vector drawing and i want to save the details of the line object not the image file. How to save the line object and how to get it back. We can use serialization with which we can save our object in file directly and can load it too. Also we can use XML Serialization which is so popular these days.

We have to just mark out objects and class with certain Attributes like XMLRoot, XMLElement, XMLAttribute and so on.


using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;

namespace XMLSerialization
{
static class Program    
{
static void Main()
{
DoSerialization();
}

private static void DoSerialization()
{
Student student1 = new Student { Name = "A", Marks = 23 };
Student student2 = new Student { Name = "B", Marks = 25 };
Students students = new Students();

students.StudentList.Add(student1);
students.StudentList.Add(student2);

XmlSerializer xmlSerialize = new XmlSerializer(students.GetType());
StreamWriter writer = new StreamWriter("a.xml");
xmlSerialize.Serialize(writer, students);
writer.Close();

StreamReader reader = new StreamReader("a.xml");
Students studentsfromFile = (Students)xmlSerialize.Deserialize(reader);

foreach (Student st in studentsfromFile.StudentList)
{
Console.WriteLine("Name : {0} Marks : {1}", st.Name, st.Marks);
}

Console.ReadLine();
}
}

[XmlRoot("Students")]
public class Students    
{
[XmlElement("Student")]
public List<Student> StudentList = new List<Student>();
}

public class Student    
{
[XmlElement("Name")]
public string Name;
[XmlElement("Marks")]
public int Marks;
}
}

Written by A.Sethi

February 10, 2009 at 10:24 am

Generics with simple example

without comments

Generics are the feature supported from the version 2.0 of .Net framework. Why it is required and where it is used. Consider a case in which you are creating a collection of objects now those objects can be int or string or anything. Now how we will design the class since we are not aware of the type used by the developer. In this case we can make of use of Generics where the type of the object will be specified only at the initialization or declaration of the collection class. Here we have to use generic type parameter T.


public class GCollection
{
private List _list = new List();

public void Add(T item)
{
_list.Add(item);
}

public T GetItem(int index)
{
return _list[index];
}
}

See the following image to get an idea how it works

Generics Sample

Generics Sample

Written by A.Sethi

February 3, 2009 at 7:55 am

Posted in General

Tagged with ,

Save Settings/Data in IsolatedStorage C#

without comments

IsolatedStorage is a storage isolated from users and assemblies. Application has to just tell the name of the file and location of the file will be handled by .net. This storage is safe has compared to keeping file in the application path and saving settings in it. Developer can save the settings of the application in the isolatedstorage in a file. Which he can recover easily. Isolated Storage is a kind of a virtual folder only. These file can have scope for user, domain, application, machine and more.

Check out the following sample


class Program    
{
static void Main(string[] args)
{
IsolatedStorageFile storage = IsolatedStorageFile.GetStore(
IsolatedStorageScope.User | IsolatedStorageScope.Assembly, null, null);

CreateFile("settings", storage);
Console.WriteLine("File Contents : \n" + ReadFile("settings", storage));

GetStoreInformation(storage);
storage.Close();
storage.Dispose();

Console.ReadLine();
}

public static void CreateFile(string fileName, IsolatedStorageFile storage)
{
IsolatedStorageFileStream stream =
new IsolatedStorageFileStream(fileName,
System.IO.FileMode.Create, storage);

StreamWriter writer = new StreamWriter(stream);
writer.WriteLine("Sample text");
writer.WriteLine("Isolated Storage");
writer.Close();
stream.Close();
}

public static string ReadFile(string fileName, IsolatedStorageFile storage)
{
IsolatedStorageFileStream stream =
new IsolatedStorageFileStream(fileName,
System.IO.FileMode.Open, storage);

StreamReader reader = new StreamReader(stream);
string data = reader.ReadToEnd();

reader.Close();
stream.Close();

return data;
}
public static void GetStoreInformation(IsolatedStorageFile storage)
{

string[] dirs =  storage.GetDirectoryNames("*");
string[] files = storage.GetFileNames("*");

Console.WriteLine("Files");
foreach (string filename in files)
{
Console.WriteLine("  |- " + filename);
}

Console.WriteLine("\nDirectories" );
foreach (string dir in dirs)
{
Console.WriteLine("  |- " + dir);
}
}

}

Written by A.Sethi

February 2, 2009 at 11:56 am

Posted in General

Tagged with , ,

Replace data in file C#

with 3 comments

There was one of the requirement to find and replace the data from the file. First we have written code to load all the data in the variable and then replace it. But it will be a problem with a huge files. So we wrote two methods to replace it line by line or chunk by chunk. Both of these methods are written below. These methods although seems correct to us but not tested. If any problem do reply back so that it can be modified

Download sample from FileFindReplace Sample

public class FileFindRelpace    
{
/// 
/// Replace the data in the Huge files searching and replacing chunk        
/// by chunk. It will create new file as filepath + ".tmp" file with        
/// replaced data        
/// 
/// Path of the file
/// Text to be replaced
/// Text with which it is replaced        
public void ReplaceLineByLine(string filePath, string replaceText, string withText)
{
StreamReader streamReader = new StreamReader(filePath);
StreamWriter streamWriter = new StreamWriter(filePath + ".tmp");

while (!streamReader.EndOfStream)
{
string data = streamReader.ReadLine();
data = data.Replace(replaceText, withText);
streamWriter.WriteLine(data);
}

streamReader.Close();
streamWriter.Close();
}

/// 
/// Replace the data in the Huge files searching and replacing chunk        
/// by chunk. It will create new file as filepath + ".tmp" file with        
/// replaced data        
/// 
/// Path of the file
/// Text to be replaced
/// Text with which it is replaced
/// Length of the data to be loaded at one go        
public void ReplaceByChunk(string filePath, string replaceText, string withText, int chunkLength)
{
int loadLength = chunkLength + replaceText.Length;
char[] buffer = new char[loadLength];
int index = 0;
int replaceLength = replaceText.Length;

StreamReader streamReader = new StreamReader(filePath);
StreamWriter streamWriter = new StreamWriter(filePath + ".tmp");

//Load the data according to the chunk length specified
//also load the extra data according to the length of
//the replace text so that chunk end and start text break
//can be handled            
while(true)
{
//Seek to the position from where we want to start and
//load the data in to the memory
                streamReader.DiscardBufferedData();
streamReader.BaseStream.Seek(index, SeekOrigin.Begin);
int count = streamReader.ReadBlock(buffer,0,loadLength);
if (count == 0) break;

//Get the data and check whether the extra loaded data
//is replaceable if yes then set end replaced flag                
string data = ConvertToString(buffer, count);
bool isEndReplaced = false;
if(count >= chunkLength)
isEndReplaced = (data.LastIndexOf(withText, chunkLength) > 0);

//Replace the data with the specified data and save the
//new data in the new file
                data = data.Replace(replaceText, withText);
if(isEndReplaced)
{
streamWriter.Write(data);
index += count;
}
else                
{
if (count >= chunkLength)
{
streamWriter.Write(data.Substring(0, data.Length - replaceLength));
index += chunkLength;
}
else                    
{
streamWriter.Write(data);
index += chunkLength;
}
}
}

streamReader.Close();
streamWriter.Close();
}

private string ConvertToString(char[] buffer, int count)
{
StringBuilder data = new StringBuilder(buffer.Length);

for (int i = 0; i < count; i++)
{
data.Append(buffer[i]);
}

return data.ToString();
}
}

Written by A.Sethi

February 2, 2009 at 9:53 am

Posted in General

Tagged with , , , ,

Handling services with the help of ServiceController from your application

without comments

You may need to get the information regarding service or need to start or stop it. Doing it from the C# is very easy with the help of ServiceController. Just create the object of the servicecontroller with the specified service and you can control that service with the help of that object


ServiceController serviceController = new ServiceController("servicename"); 

//Start it now
serviceController.Start();
serviceController.WaitForStatus(ServiceControllerStatus.Running);

//Stop it now
serviceController.Stop();
serviceController.WaitForStatus(ServiceControllerStatus.Stopped);

Also you can get verious other information from this object like status, display name, dependencies and so on.

Written by A.Sethi

January 28, 2009 at 5:46 am

Posted in C#, General

Tagged with ,

Implicit Operator Overloading

without comments

We can assign values to the int, double, float, string data types directry by writing (int l = 0) and even we can do the same to String data type which is a reference type not the value type. How to implement this method to our reference data type. Solution for this kind of requirement is Implicit operator overloading. Now let us see how it works

public class Amount
{
double _value;

/// 
/// Gets or sets the Amount value.    
///     
public double Value
{
get        
{
return _value;
}
set        
{
_value = value;
}
}

public Amount(double value)
{
_value = value;
}

public override string ToString()
{
return string.Format("{0}", Value);
}

/// 
/// Set the amount value on the basis of the double value sent    
/// 
/// Amount in double data type.
/// Implicitly created instance.    
public static implicit operator Amount(double amount)
{
Amount amt = new Amount(amount);
return amt;
}

/// 
/// Get/Return the value set to the instance of the amount class    
/// 
/// Amount Instance
/// Amount value in double    
public static implicit operator double(Amount amount)
{
return amount.Value;
}
}

We were in need to new kind of data type which is specially required for our required. We designed a class name as Amount. But problem was of assigning the values. All the time we have to use new keyword. So we implimented this implicit overloading and we got a new data type for our self. Also we can add more functions to it

Written by A.Sethi

January 1, 2009 at 11:14 am

Truncating the path (Path with with ellipses)

with 2 comments

While showing the file path in the menus/status bar/caption bar we face difficulty with long paths. Since it will increase the width/length too much and it will become odd. We can cut short that path with the help of the following function and we will utilise those path where ever we want to show with ellipses format. Now here in this particular function it is done to very simple extent. You need to pass the path it will take out the drive or base folder and append one directory name to it. Later it will add the file name to this path with ellipses ‘…’.

public string GetEllipsesPath(string fullPath)
{
string ellipsesPath = "";

if (!string.IsNullOrEmpty(fullPath))
{
string[] dirName = fullPath.Split('\\');
string fileName = Path.GetFileName(fullPath);

//Shorten the file name················
if (fileName.Length > 25)
{
fileName = fileName.Substring(0, 15) + "..." 
+ fileName.Substring(fileName.Length - 5, 5);
}

//Shortten the complete path
                ellipsesPath = Path.GetPathRoot(fullPath) + (dirName.Length > 2 ? dirName[1]
+ @"\..\" : "") + fileName;
}

return ellipsesPath;
}

This function can further be modified having another parameter named ‘length’. with that we can give developer option of having the of the specified size. You can also use the api function to perform the same function .

[DllImport("shlwapi.dll")]
private static extern bool PathCompactPathEx(string pszOut, 
string szPath, int cchMax, int dwFlags);

Written by A.Sethi

December 31, 2008 at 4:13 am

Posted in C#, General

Tagged with ,