Spot the web RSS 2.0
# Monday, March 10, 2008

This article discusses the delegate type and how it can be used to point to methods in the application which can be invoked at later time. This article demonstrates also the delegate ability to multicast and delegate covariance.

A delegate is a type-safe object that can point to another method (or possibly multiple methods) in the application, which can be invoked at later time.

Delegates also can invoke methods Asynchronously.

A delegate type maintains three important pices of information :

  1. The name of the method on which it make calls.
  2. Any argument (if any) of this method.
  3. The return value (if any) of this method.

Defining a Delegate in C#

when you want to create a delegate in C# you make use of delegate keyword.

The name of your delegate can be whatever you desire. However, you must define the delegate to match the signature of the method it will point to. fo example the following delegate can point to any method taking two integers and returning an integer.

public delegate int DelegateName(int x, int y);

A Delegate Usage Example

namespace MyFirstDelegate

{

    //This delegate can point to any method,

    //taking two integers and returning an

    //integer.

    public delegate int MyDelegate(int x, int y);

    //This class contains methods that MyDelegate will point to.

    public class MyClass

    {

        public static int Add(int x, int y)

        {

            return x + y;

        }

        public static int Multiply(int x, int y)

        {

            return x * y;

        }

    }

    class Program

    {

        static void Main(string[] args)

        {

            //Create an Instance of MyDelegate

            //that points to MyClass.Add().

            MyDelegate del1 = new MyDelegate(MyClass.Add);

            //Invoke Add() method using the delegate.

            int addResult = del1(5, 5);

            Console.WriteLine("5 + 5 = {0}\n", addResult);

            //Create an Instance of MyDelegate

            //that points to MyClass.Multiply().

            MyDelegate del2 = new MyDelegate(MyClass.Multiply);

            //Invoke Multiply() method using the delegate.

            int multiplyResult = del2(5, 5);

            Console.WriteLine("5 X 5 = {0}", multiplyResult);

            Console.ReadLine();

        }

    }
}

Delegate ability to Multicast

Delegate ability to multicast mean that a delegate object can maintain a list of methods to call, rather than a single method
if you want to add a method to the invocation list of a delegate object , you simply make use of the overloaded += operator, and if you want to remove a method from the invocation list you make use of the overloaded operator -= .

Note:Multicast delegate must contain only methods that return void, or you will get a run time exception.

A Multicast Delegate Example

namespace MyMulticastDelegate

{

    //this delegate will be used to call more than one

    //method at once

    public delegate void MulticastDelegate(int x, int y);

    //This class contains methods that MyDelegate will point to.

    public class MyClass

    {

        public static void Add(int x, int y)

        {

            Console.WriteLine("You are in Add() Method");

            Console.WriteLine("{0} + {1} = {2}\n", x, y, x + y);

        }

        public static void Multiply(int x, int y)

        {

            Console.WriteLine("You are in Multiply() Method");

            Console.WriteLine("{0} X {1} = {2}", x, y, x * y);

        }

    }

    class Program

    {

        static void Main(string[] args)

        {

            //Create an Instance of MulticastDelegate

            //that points to MyClass.Add().

            MulticastDelegate del = new MulticastDelegate(MyClass.Add);

            //using the same instance of MulticastDelegate

            //to call MyClass.Multibly() by adding it to it's

            //invocation list.

            del += new MulticastDelegate(MyClass.Multiply);

            //Invoke Add() and  Multiply() methods using the delegate.

            //Note that these methods must have a void return vlue

            Console.WriteLine("****calling Add() and Multibly() Methods.****\n\n");

            del(5, 5);

 

            //removing the Add() method from the invocation list

            del -= new MulticastDelegate(MyClass.Add);

            Console.WriteLine("\n\n****Add() Method removed.****\n\n");

            //this will invoke the Multibly() method only.

            del(5, 5);

        }

    }

}

Delegate Covariance

Assume you are designing a delegate that can point to methods returning a custom class type:

//Define a delegate pointing to methods returning Employee types.

public delegate Employee EmployeeDelegate();

if you were to derive a new class from Employee Type named SalesEmployee and wish to create a delegate type that can point to methods returning this class type you would be required to define an entirely new delegate to do so

//a new  delegate pointing to methods returning SalesEmployee types.

public delegate SalesEmployee SalesEmployeeDelegate();

Example

namespace MyEmployeesDelegate

{

    //Define a delegate pointing to methods returning Employee types.

    public delegate Employee EmployeeDelegate();

    //a new  delegate pointing to methods returning SalesEmployee types.

    public delegate SalesEmployee SalesEmployeeDelegate();

    class Program

    {

        public static Employee GetEmployee()

        {

            return new Employee();

        }

        public static SalesEmployee GetSalesEmployee()

        {

            return new SalesEmployee();

        }

        static void Main(string[] args)

        {

            EmployeeDelegate empDel = new EmployeeDelegate(GetEmployee);

            Employee emp = empDel();

            SalesEmployeeDelegate salesEmpDel = new SalesEmployeeDelegate(GetSalesEmployee);

            SalesEmployee emp2 = salesEmpDel();

        }

    }

    public class Employee

    {

        protected string firstName;

        protected string lastName;

        protected int Age;

        public Employee()

        { }

        public Employee(string fName, string lName, int age)

        {

            this.firstName = fName;

            this.lastName = lName;

            this.Age = age;

        }

 

    }

    public class SalesEmployee : Employee

    {

        protected int salesNumber;

        public SalesEmployee()

        { }

        public SalesEmployee(string fName, string lName, int age, int sNumber): base(fName, lName, age)

        {

            this.salesNumber = sNumber;

        }

    }

}

It would be ideal to build a single delegate type that can point to methods returning either Employee or SelesEmployee types.
Covariance allows you to build a single delegate that can point to methods returning class types related by classical inheritance.

Delegate Covariance Example

namespace DelegateCovariance

{

    //Define a single delegate that may return an Employee

    // or SalesEmployee

    public delegate Employee EmployeeDelegate();

    class Program

    {

        public static Employee GetEmployee()

        {

            return new Employee();

        }

        public static SalesEmployee GetSalesEmployee()

        {

            return new SalesEmployee();

        }

        static void Main(string[] args)

        {

            EmployeeDelegate emp = new EmployeeDelegate(GetEmployee);

            Employee emp1 = emp();

            EmployeeDelegate empB = new EmployeeDelegate(GetSalesEmployee);

            //to obtain a derived type you must perform an explicit cast.

            SalesEmployee emp2 = (SalesEmployee)empB();

        }

    }

    public class Employee

    {

        protected string firstName;

        protected string lastName;

        protected int Age;

        public Employee()

        { }

        public Employee(string fName, string lName, int age)

        {

            this.firstName = fName;

            this.lastName = lName;

            this.Age = age;

        }

    }

    public class SalesEmployee : Employee

    {

        protected int salesNumber;

        public SalesEmployee()

        { }

        public SalesEmployee(string fName, string lName, int age, int sNumber): base(fName, lName, age)

        {

            this.salesNumber = sNumber;

        }

    }

}

I hope you are now have a good idea with the creation and usage of delegates types.

Monday, March 10, 2008 10:28:46 AM (Jerusalem Standard Time, UTC+02:00)  #    Comments [0] - Trackback
.Net | AJAX | Microsoft | Programming | C#
# Sunday, March 09, 2008

A common - and desirable - technique for constructing JavaScript-based web applications is that of progressive enhancement: only providing capable browsers with the features that they are capable of utilizing - but providing incapable browsers with an adequate, albeit degraded, experience otherwise.

This provides the best of both worlds: Users of modern browsers (the majority audience) can get the best experience while those that are using incapable browsers (such as most mobile devices) will still get an interface that suits them well.

There's one thing, overriding in all of this, however: Progressive enhancement is nearly only ever applied to the JavaScript functionality of web applications. Presumably it's assumed that if a browser is capable of supporting the desired JavaScript features of an application then it must, also, be capable of supporting the specific CSS styling as well.

One technique that has greatly interested me, as of late, is one employed by the Filament Group (a local design shop here in Boston): Progressive CSS Enhancement. The premise is that progressive enhancement is done with page styling in mind, primarily, rather than from a purely-JavaScript perspective.

This is particularly important for a couple reasons:

  • It should be easy to degrade page styling in a manner that isn't reliant upon CSS browser hacks - this technique makes it so.
  • Not all pages utilize heavy JavaScript (and, thus, progressive JavaScript enhancement does not apply to them).

Their technique works as follows: You choose to provide the user with, either, the enhanced or the decreased experience by default. In either case a basic script is run which attempts to verify a couple CSS styling behaviors along with some basic JavaScript functionality (just enough to be able to run the test).

A couple of the CSS techniques that they test for:

  • Box model: make sure the width and padding of a div add up properly using offsetWidth.
  • Positioning: position a div and check its positioning using offsetTop and offsetLeft.
  • Float: float 2 divs next to each other and evaluate their offsetTop values for equality.
  • Clear: test to make sure a list item will clear beneath a preceding floated list item.
  • Overflow: wrap a tall div with a shorter div with overflow set to 'auto', and test its offsetHeight.

With those in place you can pretty safely begin designing a useful CSS-based layout. Note that the experience will only ever be upgraded if all of the tests pass - if any fail then it simply won't continue. Obviously there'll still exist some browser discrepancies (like in the differences in the box model between Internet Explorer 6 and most other browsers) but that's usually an acceptable level of hackage (meaning that you won't have to deviate much from what you're already doing).

The actual implementation is quite simple. It consists of a number of JavaScript-based rules that test for behavior. For example the following rule tests for a working box model:

var newDiv = document.createElement('div');
document.body.appendChild(newDiv);
newDiv.style.visibility = 'hidden';
newDiv.style.width = '20px';
newDiv.style.padding = '10px';
var divWidth = newDiv.offsetWidth;
if(divWidth != 40) {document.body.removeChild(newDiv); return false;}

That check, alone, is able to knock off a number of older browser whom aren't able to successfully implement that CSS behavior. Currently all the rules are in a large code block, which makes maintenance unwieldily. I think that this library could definitely benefit from extensibility (being able to add/remove rules that you wish to honor).

When it comes time to actually use this technique within your application there are a number of strategies that you can use. However, for the sake of discussion here, let's assume that you're sending, by default, the degraded experience to the client (optionally upgrading if the browser is capable). Then you would be able to use these two techniques:

  • A class of "enhanced" is assigned to the body element to be used for optional CSS scoping (such as: body.enhanced {background: red;}).
  • Any links to alternate stylesheets that have a class of "enhanced" will be enabled.

In this manner you can specify all of your stylesheets in your header with some disabled (being alternate stylesheets) or with some CSS rules being only applied with the body.enhanced match.

Their implementation also allows you to only execute JavaScript if all the rules pass - however I'm not sure if that's an acceptable solution, in this situation. If you want to verify that your desired JavaScript functionality is able to operate then you should check for just that. However, in this case, we can get the other side of the equation: Verifying that CSS works as you would expect it to, knowing that an adequate experience can be provided.

If you're curious as to which devices are supported by the default rules in the test file you can view the result matrix on the tool's site.

I definitely think that this technique has a lot of merit, especially in the realm of mobile-accessible web sites. Since it's virtually impossible to design, and test, your pages to work on such a large number of obscure platforms this degraded strategy is really one that will help to benefit both you, and your users, in the long run.

Sunday, March 09, 2008 11:24:37 AM (Jerusalem Standard Time, UTC+02:00)  #    Comments [0] - Trackback
CSS | Programming | Web Design
# Friday, March 07, 2008

This article explains how you can extract all Tables, including Data, to an Excel file. Every Table will have it's own worksheet. The code does need an excel application installed on the server, while it's using Office Interop.

To get this code to work, you need to add a reference to Excel.dll by using Add Reference on the project and selecting Microsoft Excel 9.0 (or 10.0) Object Library from the COM tab on the Add Reference dialog.

And then import the following namespace:

Imports System.Runtime.InteropServices.Marshal


Now add the following class to your project:

Private Sub create(ByVal sDatabaseName As String)
Dim dsTables As DataSet = New DataSet

'Get all Tables from database
dsTables = getAllTables(sDatabaseName)
'Create Excel Application, Workbook, and WorkSheets
Dim xlExcel As New Excel.Application
Dim xlBooks As Excel.Workbooks
Dim xlBook As Excel.Workbook
Dim tblSheet As Excel.Worksheet
Dim xlCells As Excel.Range
Dim sFile As String

'File name for the excel file
sFile = Server.MapPath("~\Sheets\" & sDatabaseName & "_data.xls")

xlExcel.Visible = False : xlExcel.DisplayAlerts = False
xlBooks = xlExcel.Workbooks
xlBook = xlBooks.Add

For i As Integer = 0 To dsTables.Tables.Count - 1
    tblSheet = xlBook.Worksheets.Add
    tblSheet.Name = dsTables.Tables(i).TableName
    xlCells = tblSheet.Cells
    'Fill all cells with data
    GenerateExcelFile(dsTables.Tables(i), xlCells)
Next

'Remove initial excel sheets. Within a try catch because the database
'could be empty (a workbook without worksheets is not allowed)
Try
    Dim
SheetCount As Integer = xlExcel.Sheets.Count
    CType(xlExcel.Sheets(SheetCount - 0), Excel.Worksheet).Delete()
    CType(xlExcel.Sheets(SheetCount - 1), Excel.Worksheet).Delete()
    CType(xlExcel.Sheets(SheetCount - 2), Excel.Worksheet).Delete()
Catch ex As Exception

End Try

'Save the excel file
xlBook.SaveAs(sFile)

'Make sure all objects are disposed
xlBook.Close()
xlExcel.Quit()
ReleaseComObject(xlCells)
ReleaseComObject(tblSheet)
ReleaseComObject(xlBook)
ReleaseComObject(xlBooks)
ReleaseComObject(xlExcel)
xlExcel = Nothing
xlBooks = Nothing
xlBook = Nothing
tblSheet = Nothing
xlCells = Nothing
'Let the Garbage Collector know it can get to work
GC.Collect()

'Export Excel for download
Try
HttpContext.Current.Response.ContentType = "application/octet-stream"
HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + System.IO.Path.GetFileName(sFile))
HttpContext.Current.Response.Clear()
HttpContext.Current.Response.WriteFile(sFile)
HttpContext.Current.Response.End()
Catch ex As Exception
'An exception will be thrown, but can just be ignored
End Try

End Sub


To generate the individual sheets, the following Sub is used:

Private Sub GenerateExcelFile(ByRef table As DataTable, ByVal xlCells As Excel.Range)
Dim dr As DataRow, ary() As Object
Dim
iRow As Integer, iCol As Integer

'Output Column Headers
For iCol = 0 To table.Columns.Count - 1
    xlCells(1, iCol + 1) = table.Columns(iCol).ToString
    xlCells(1).EntireRow.Font.Bold =
True
Next

'Output Data
For iRow = 0 To table.Rows.Count - 1
    dr = table.Rows.Item(iRow)
    ary = dr.ItemArray
    For iCol = 0 To UBound(ary)
        xlCells(iRow + 2, iCol + 1) = ary(iCol).ToString
        Response.Write(ary(iCol).ToString & vbTab)
    Next
Next
xlCells.Columns.AutoFit()
End Sub


And now the trick to getting all tables and data from a database:

Public database as String

Public ReadOnly Property getAllTables(ByVal sDB As String) As DataSet
    Get
       
database = sDB
        Dim m_dshelp As DataSet = New DataSet
        getRequestedAllTables(m_dshelp)
        Return m_dshelp
    End Get
End
Property


Private Function getRequestedAllTables(ByRef p_dataset As DataSet) As Boolean

'Retrieve all tablenames from the database:
Dim sSQL As String
Dim
dsTables As DataSet = New DataSet
sSQL =
"SELECT [TableName] = so.name, [RowCount] = MAX(si.rows) " & _
"FROM sysobjects so, sysindexes si " & _
"WHERE so.xtype = 'U' AND si.id = OBJECT_ID(so.name) AND si.rows > 0 " & _
"GROUP BY so.name " & _
"ORDER BY 2 DESC"

getData(sSQL, "Tables", dsTables)

'Loop thrue all tables and do a SELECT *. Then add them to the dataset
For i As Integer = 0 To dsTables.Tables(0).Rows.Count - 1
    sSQL =
"SELECT * FROM " & dsTables.Tables(0).Rows(i).Item(0)
    getData(sSQL, dsTables.Tables(0).Rows(i).Item(0), p_dataset)
Next
End
Function


Private Function getData(ByVal p_sql As String, ByVal p_table As String, ByRef pdataset As DataSet) As Boolean

Dim objDataAdapter As SqlDataAdapter
Dim objcommand As SqlCommand
objcommand
= New SqlCommand(p_sql, getConnection)
objDataAdapter =
New SqlDataAdapter(objcommand)
objDataAdapter.Fill(pdataset, p_table)
End Function


Private Function getConnection() As SqlConnection
If (ConfigurationManager.AppSettings("SQLPW") <> "") Then
    getConnection = New SqlConnection("Server=" & _
    ConfigurationManager.AppSettings("
SQLserver") & ";password=" & _
    ConfigurationManager.AppSettings(
"SQLPW") & "; user=" & _
    ConfigurationManager.AppSettings("
SQLUser") & ";database=" & database)
Else
    getConnection = New SqlConnection("Data Source=" & _
   ConfigurationManager.AppSettings(
"SQLserver") & ";Initial Catalog=" & _
    database &
";Integrated Security=True")
End If
End Function

Friday, March 07, 2008 11:42:11 AM (Jerusalem Standard Time, UTC+02:00)  #    Comments [0] - Trackback
.Net | Programming | Visual Studio
Navigation
Archive
<March 2008>
SunMonTueWedThuFriSat
2425262728291
2345678
9101112131415
16171819202122
23242526272829
303112345
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2010
Guy Levin
Sign In
Statistics
Total Posts: 63
This Year: 0
This Month: 0
This Week: 0
Comments: 14
Themes
All Content © 2010, Guy Levin