Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Monday, July 13, 2009

Use your own VB.Net and C# Libraries in VB6


There are times when you need to use one of your .Net DLL’s in a Visual Basic 6 application.

Why should I bother, you ask? Let’s say that you want to retrieve information from a .Net Web Service from your VB6 app, it is easiest and fastest to code the call from a .Net Library than from VB6. Or you may have a Security Library that handles the user authentication and authorization of all the apps in your company, but you have some old VB6 programs that you can’t get rid of. In all these cases, it would be helpful to just invoke a method of your .Net Library from the VB6 code.

There is a series of requisites to make a .Net DLL usable from VB6.

1. Prepare your Class.

In your DLL, you should have a Main or Entry Point Class. That is the class that the VB6 app will call and use. It doesn’t matter what your other classes do, you just need to code the Main Class with these points in mind:

- Don’t use Shared or Static Functions. VB6 won’t be able to call these functions. As long as they are not been called from VB6, it doesn’t matter if you have Static functions in your code.

- Don’t user parameterized Constructors. To instantiate your class from VB6 there must be a default constructor (that doesn’t receive any parameters). Again, you can have all the constructors you want, but you will be able to use only the default from VB6.

- Add an Import (VB.Net) or Using (C#) to this namespace: System.Runtime.InteropServices


2. Prepare your DLL.

You have to change some settings to your project in order to make it usable from VB6:

- Sign the Assembly. Go to Project -> Properties and in the Signing Tab check the “Sign the Assembly” option. Then choose a strong name for your key file selecting “”, type a name and press OK (you don’t need to protect the key with a password)

- Make the Project COM Visible. Go to the Application tab in your project properties and click in “Assembly Information…” button. Check the option “Make assembly COM-Visible”. Now that you are here, fill the assembly information (product name, version, etc.) as this info will be displayed in VB6 when you reference to it.


- Make Intellisense work in VB6. You need to open the file AssemblyInfo.vb or AssemblyInfo.cs. You can open it from the Solution Explorer under the Properties folder. If you can’t see it, click the “Show All Files” button in the toolbar of the Solution Explorer. What you need is to add this line there (it could be anywhere in the file):

C#: [assembly: ClassInterface(ClassInterfaceType. AutoDual)]
VB.Net:


(If you have problems, you may come back here and change AutoDual to AutoDispatch)

- Add the path of the key.snk. In the AssemblyInfo file, add the path of the key you created previously:

C#: [assembly: AssemblyKeyFile(@"C:\...\MyKey.snk")]
VB.Net:


3. Prepare Client Machine.

When you build your project, you will notice Visual Studio generated two files: mydll.DLL and my dll.TLB. The second file is a description of the DLL used by VB6. In order to use the DLL from VB6 you need to register the assembly:

- First open a command prompt (Start -> Run -> “cmd”) and go to the .Net Framework directory:

> cd C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727

- Now use the regasm command to register both DLL and TLB:

> regasm C:\[path]\MyDll.dll /tlb:MyDll.tlb

(If you need to uninstall the the .Net reference, use "regasm /u")

You will need to do this for your Development Machine and for the Client Machine. You can create an installer or a batch program to register the DLL and TLB in the client machine.

The last step is simple: open Visual Basic 6 Environment, go to Project -> References… and browse for your DLL.

Congratulations! Now you can instantiate your .Net Class from Visual Basic 6.

Wednesday, May 6, 2009

Comparing your objects: IComparable & IComparer Interfaces (Part III)

Now, here is a useful example of IComparable and ICompare. Let's bind a List of our Business Objects to a DataGridView and Sort the list by column when a header column is double-clicked.

Create a WinForms application. Let's start with a form with a button and a DataGridView.
The button will create a List of Employees (see the previous post) and populate it. After that, we'll bind the list to our datagrid:

private void btnLoad_Click(object sender, EventArgs e)

{

List<Employee> employees = new List<Employee>();

//add employees to the list

employees.Add(new Employee("1", "Elijah", "Baley", 5000.50));

employees.Add(new Employee("2", "Daneel", "Olivaw", 3650.80));

employees.Add(new Employee("3", "Hari", "Seldon", 8450.25));

//bind the datagrid

dgvEmployees.DataSource = employees;

}



If you run the app and click the button you will get something like this:



Let's get to the Sort part. Remember we created some Comparer classes for our Employee Class. However, those comparers will work only to sort in an Ascending order. Let's create more to sort in Descending order. The only change here is that we will compare the objects backwards:

In ascending order we compare like this:
x.property.CompareTo(y.property)
In descending order we just use:
y.property.CompareTo(x.property)

So here you have all the comparers we will use:

//ASCENDING

public class EmployeeComparerFirstName : IComparer<Employee>

{

public int Compare(Employee x, Employee y)

{

return x.FirstName.CompareTo(y.FirstName);

}

}

public class EmployeeComparerLastName : IComparer<Employee>

{

public int Compare(Employee x, Employee y)

{

return x.LastName.CompareTo(y.LastName);

}

}

public class EmployeeComparerSalary : IComparer<Employee>

{

public int Compare(Employee x, Employee y)

{

return x.Salary.CompareTo(y.Salary);

}

}

//DESCENDING

public class EmployeeComparerEmployeeIdDSC : IComparer<Employee>

{

public int Compare(Employee x, Employee y)

{

return y.EmployeeId.CompareTo(x.EmployeeId);

}

}

public class EmployeeComparerFirstNameDSC : IComparer<Employee>

{

public int Compare(Employee x, Employee y)

{

return y.FirstName.CompareTo(x.FirstName);

}

}

public class EmployeeComparerLastNameDSC : IComparer<Employee>

{

public int Compare(Employee x, Employee y)

{

return y.LastName.CompareTo(x.LastName);

}

}

public class EmployeeComparerSalaryDSC : IComparer<Employee>

{

public int Compare(Employee x, Employee y)

{

return y.Salary.CompareTo(x.Salary);

}

}



You may wonder why we have a desceding comparer for EmployeeId property but not the ascending one. That's because the ascending comparer for that property is the default comparer in our Employee Class when it implements IComparable. That's in the CompareTo method (see part I).

We can use any of this comparers to sort the columns of our datagrid, the problem is how to know which comparer should we use. To decide that we'll create a method that will return the right IComparer we need, based on the name of the property that column is bound to and the sort order.

private IComparer<Employee> getEmployeeComparer(String propertyName, System.Windows.Forms.SortOrder sortDirection)

{

switch (propertyName)

{

case "FirstName":

if (sortDirection == SortOrder.Ascending)

return new EmployeeComparerFirstName();

else

return new EmployeeComparerFirstNameDSC();

case "LastName":

if (sortDirection == SortOrder.Ascending)

return new EmployeeComparerLastName();

else

return new EmployeeComparerLastNameDSC();

case "Salary":

if (sortDirection == SortOrder.Ascending)

return new EmployeeComparerSalary();

else

return new EmployeeComparerSalaryDSC();

default:

if (sortDirection == SortOrder.Ascending)

return null;

else

return new EmployeeComparerEmployeeIdDSC();

}

}


You can see that if the property name is not found, the list will be sorted by EmployeeId. Additionally, if the sort order is ascending the method will return null. That's because if the Sort method of List receives no comparer at all, it'll use the default comparer of the object: the CompareTo method.

You can write this method in the Employee class making it static or in a different class with all the other comparers. For now let's just put it in the code of our Form.

The next step is to handle the event ColumnHeaderMouseDoubleClick of the DataGridView, so when the user double-clicks the header of a column we will sort that column.

private void dgvEmployees_ColumnHeaderMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)

{

//get list from datasource

List<Employee> employees = (List<Employee>)dgvEmployees.DataSource;

//set sort order

SortOrder sortOrder = (dgvEmployees.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending);

//sort list

employees.Sort(getEmployeeComparer(dgvEmployees.Columns[e.ColumnIndex].DataPropertyName, sortOrder));

//remove sort glyph from any other column

unmarkSortedColumns(dgvEmployees);

//set sort glyph for current column

dgvEmployees.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = sortOrder;

//refresh grid to see the changes

dgvEmployees.Refresh();

}


Here is the big thing.
1) We cast the data source of the DataGridView to an Employee List.

List<Employee> employees = (List<Employee>)dgvEmployees.DataSource;


2) We decide the new sort order. If the column is already sorted with ascending order then we will sorted descending, else if the sort order is descending or the column is not sorted at all we will use ascending order.

SortOrder sortOrder = (dgvEmployees.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending);


3) Now we sort the List (notice that we sort the List and not the DataGridView) using our GetEmployeeComparer method to get the right comparer we need. To do this we pass the sort order and the name of the property. To get the name of the property just look at the DataPropertyName attribute of the current column.

employees.Sort(getEmployeeComparer(dgvEmployees.Columns[e.ColumnIndex].DataPropertyName, sortOrder));


4) An additional step is to remove the sorted glyph to any other column that was previously sorted. To do this we write the function unmarkSortedColumns passsing the our DataGridView, this way we can reuse this method when sorting other grids.

private void unmarkSortedColumns(DataGridView dataGrid)

{

foreach (DataGridViewColumn col in dataGrid.Columns)

{

if (col.HeaderCell.SortGlyphDirection != SortOrder.None)

col.HeaderCell.SortGlyphDirection = SortOrder.None;

}

}


5) After that we set the sort glyph to the current column we are sorting. Remember that the SortGlyphDirection property or the HeaderCell of our column is the one that sets that arrow icon in the column header that indicates the column is sorted.

dgvEmployees.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = sortOrder;


6) And the last thing, but not less important, is to refresh the DataGridView. Otherwise, how would it know that the List has been order?

dgvEmployees.Refresh();


And that's it for now, your DataGrid will be sorted by the column you double-click:



In conclusion: you can implement IComparable and IComparer to compare you business objects by some property or based on an algorithm. A practical usage of these interfaces is to sort a list of business objects and sort the columns of a DataGridView when it is bound to a list of business objects.

That's it for this serie of posts, however expect a surprise about topic. soon.

See Part I and Part II

Monday, May 4, 2009

Comparing your objects: IComparable & IComparer Interfaces (Part II)

In a previous post we saw that implementing the IComparable Interface allows an instance of our class to be compared against another object of the same type. We can choose a property of our class as the default criteria of comparison.

But what if we want to have multiple criteria for comparing objects? With IComparable we can have only one compareTo method, but IComparer helps us to compare objects using different criteria.

A big difference between these two Interfaces is that when our class implements IComparable it adds a compareTo method to our Class, but IComparer must be implemented in a different class. So we are going to have a Comparer class to help us compare our objects.

To illustrate the usage of the IComparer Interface, let's use the example of the previous post. This is our Employee class that implements IComparable and uses the EmployeeId property as the comparison criteria:

public class Employee : IComparable<Employee>

{

//Properties

private String employeeId;

public String EmployeeId

{

get { return employeeId; }

set { employeeId = value; }

}

private String firstName;

public String FirstName

{

get { return firstName; }

set { firstName = value; }

}

private String lastName;

public String LastName

{

get { return lastName; }

set { lastName = value; }

}

private Double salary;

public Double Salary

{

get { return salary; }

set { salary = value; }

}

//Constructor

public Employee(String id, String firstName, String lastName, Double salary)

{

this.employeeId = id;

this.firstName = firstName;

this.lastName = lastName;

this.salary = salary;

}

//IComparable

#region IComparable Members

int IComparable<Employee>.CompareTo(Employee other)

{

return this.EmployeeId.CompareTo(other.EmployeeId);

}

#endregion

}



Now, we'll create a Comparer class to compare Employee objects using the FirstName property.

public class EmployeeComparerFirstName : IComparer<Employee>

{

public int Compare(Employee x, Employee y)

{

return x.FirstName.CompareTo(y.FirstName);

}

}


We are using the Generic version of the Interface but you can use the other one (see in Part I how to do it).

And this way, you can create a Comparer class for each property of your class, or even code an algorithm inside the Compare method. For now, let's create another Comparer for the salary:

public class EmployeeComparerSalary : IComparer<Employee>

{

public int Compare(Employee x, Employee y)

{

return x.Salary.CompareTo(y.Salary);

}

}


So, comparing your objects is simple. But what is the purpose? Here is an example of using IComparer and IComparable to sort a List of Employees:

class Program

{

static void Main(string[] args)

{

List<Employee> employees = new List<Employee>();

//add employees to the list

employees.Add(new Employee("1", "Elijah", "Baley", 5000.50));

employees.Add(new Employee("2", "Daneel", "Olivaw", 3650.80));

employees.Add(new Employee("3", "Hari", "Seldon", 8450.25));

printList(employees);

//sort by first name

employees.Sort(new EmployeeComparerFirstName());

printList(employees);

//sort by salary

employees.Sort(new EmployeeComparerSalary());

printList(employees);

//sort by the default field: employee ID

employees.Sort();

printList(employees);

Console.ReadKey();

}

//method to print the list

static void printList(List<Employee> list)

{

foreach (Employee employee in list)

{

Console.WriteLine(employee.EmployeeId + " " + employee.FirstName + " " +

employee.LastName + " " + employee.Salary.ToString());

}

Console.WriteLine("------------------------------------");

}

}



It's a console application that creates a List of Employees and sorts it using our comparers. The Sort method of List of Employees receives either a Comparer or nothing at all (in an overloaded version of the method). If you don't provide a Comparer, the Sort method will use the compareTo method of the class.

Run it and see it for yourself. Play with it. You can notice that if Employees does Not implements IComparable and you don't provide a Comparer when sorting the list, you will get an exception because the Sort method doesn't know how to compare the employees.

Another point is that if your are using a Generic List (like in the example) you have to use the Generic versions of IComparer and IComparable (to know how to use the non-generic versions go to the previous post).

A really good usage of Comparers is when you bind your List of objects to a Control and want to use the Sort functionality of the Control. In the next post we'll see how to sort a DataGridView in WinForms when it is bound to a List of business objects.

Monday, April 20, 2009

Comparing your objects: IComparable & IComparer Interfaces.

Have you ever try to make your objects “Sortables”? Some WinForms controls have sort functionality when you bind them to a DataTable or other DataSources; one of those is the DataGridView. However, when you bind them to a list of your own business objects, sorting it’s not completely automatic.

That's when Comparing Objects enters to scene.

To sort a list of values (or objects), the control needs to know how to compare them. The interfaces IComparable and IComparer are provided for this goal.


When implementing the IComparable interface, we are saying that a specific instance of the class can be compared to another one.

Let’s say we have an Employee class:

class Employee : IComparable

{

private String employeeId;

private String firstName;

private String lastName;
private Double salary;

}

(You may use properties of the class. For simplicity we’ll use fields)

We can implement the inteface IComparable; the IDE will help us to generate the functions of the interface by putting the cursor in the name of the inteface and clicking “Implement Interface”.


I like the explicitly way, but it’s a matter of taste (or company standards)

class Employee : IComparable<Employee>

{

private String employeeId;

private String firstName;

private String lastName;

private Double salary;


#region IComparable Members

int IComparable.CompareTo(Object obj)
{


}

#endregion

}


Now you just have to decide how you are comparing the Employees. When you say EmployeeA > EmployeeB, how the employees should be compared? Employee A is greatest than B because of his salary? Let’s say that the default comparison will be the employee ID in order to don’t hurt anyone’s feelings.

int IComparable.CompareTo(Object obj)
{

this.employeeId.CompareTo(((Employee)obj).employeeId);

}


We are comparing the employee ID of our object against the employee ID of the object received as parameter in the function.

Here we have two things to point out:
A) We are using the CompareTo method of the String Class; after all, employee ID is a String; and
B) We have to cast the object received as an Employee.

Point A is not an issue. Usually, we are going to have an ID or some identifier property in our class to compare against it. This ID will often be a String, int, DateTime or some sort of base type. The good news is that all of these types implements IComparable, so they have the CompareTo method. But if you need to use a non-IComparable property or need a whole specific algorithm to compare two objects, you can change the CompareTo method to fit your needs. The only thing you have to remember is to return an integer representing if the instance is less, equal or greater than the parameter.

Instance < Object returns a value less than zero
Instance == Object returns zero
Instance > Object returns a value grater than zero

Now, the real problem comes with point B. What if we received an object that is not an Employee? We would have an Exception in that case. So, in order to fix that, we’ll use the Generic version of the IComparable interface that allows only objects of the specified typed.


class Employee : IComparable<Employee>

{

private String employeeId;

private String firstName;

private String lastName;

private Double salary;


#region IComparable Members

int IComparable<Employee>.CompareTo(Employee other)
{

this.employeeId.CompareTo(other.employeeId);

}

#endregion

}


Now we are sure we are comparing two Employees.

This is it for IComparable Inteface. In a (near) future post we'll see the IComparer Interface, the differences between these two and an example of using them.