Showing posts with label Architecture. Show all posts
Showing posts with label Architecture. Show all posts

Monday, March 17, 2014

Using RDLC with ASP.Net MVC to export report in PDF/Excel format

To export a report in PDF/Excel format using RDLC.


  1. Create a ASP.Net MVC web site.
  2. Add a RDLC report and creates its DataSources and Design the report as per requirement.
  3. Create an action method in your controller and use following code.

public ActionResult GetPdfReport(int month, int year, int snapshottypeid, long taskrunid)
{

//Step 1 : Create a Local Report.
LocalReport localReport = new LocalReport();

//Step 2 : Specify Report Path.
localReport.ReportPath = Server.MapPath("~/Content/UnAssignedLevelsReport.rdlc");

//Step 3 : Create Report DataSources
ReportDataSource dsUnAssignedLevels = new ReportDataSource();
dsUnAssignedLevels.Name = "UnAssignedLevels";
dsUnAssignedLevels.Value = dataSet.UnAssignedLevels;

ReportDataSource dsReportInfo= new ReportDataSource();
dsReportInfo.Name = "ReportInfo";
dsReportInfo.Value = dataSet.ReportInfo;

//Step 4 : Bind DataSources into Report
localReport.DataSources.Add(dsUnAssignedLevels);
localReport.DataSources.Add(dsReportInfo);

//Step 5 : Call render method on local Report to generate report contents in Bytes array
string deviceInfo = "<DeviceInfo>" +
"  <OutputFormat>PDF</OutputFormat>" +
"</DeviceInfo>";
Warning[] warnings;
string[] streams;
string mimeType;
byte[] renderedBytes;
string encoding;
string fileNameExtension;
//Render the report          
renderedBytes = localReport.Render("PDF", deviceInfo, out mimeType, out encoding, out fileNameExtension, out streams, out warnings);


//Step 6 : Set Response header to pass filename that will be used while saving report.
Response.AddHeader("Content-Disposition",
"attachment; filename=UnAssignedLevels.pdf");

//Step 7 : Return file content result
return new  FileContentResult(renderedBytes, mimeType);
}

4. While deploying code to a development/production server make sure following assemblies are referred from correct location and for them set CopyLocals as True.


Friday, January 31, 2014

Namespaces in Javascript

Namespacing in Javascript can be achieved in following ways

1. Single global variables
2. Prefix namespacing
3. Object literal notation
4. Nested namespacing
5. Immediately-invoked Function
6. Expressions
7. Namespace injection

Lets go in detail..

Single Global Variables:
Here we define a single Global variable which holds all methods and properties of object.

Ex.
var myExApplication =  (function () { 
        function(){
            //...
        },
        return{
            //...
        }
})();

Disadvantage: There are high chances of conflicts same variable could be used in some other part of code.


Prefix Namespacing:
Here we select a unique prefix namespace we wish to  use (in this example, myExApplication_)  and then define any methods, variables, or other objects after the  prefix as follows

Ex.
var myExApplication_propertyA = {};
var myExApplication_propertyB = {};
function myExApplication_myMethod(){ 
  //...
}

Disadvantage: We may end up having huge number of global variables thus tough manageable code.

Object Literal Notation:
Here an object contains a collection of key-value pairs with a colon separating each pair of keys and values, where keys can also represent new namespaces.

Ex.
var myExConfig = { //myExConfig is a JSON object and it contains all methods and props.

    language: "english",

    defaults: {
        enableGeolocation: true,
        enableSharing: false,
        maxPhotos: 20
    },

    theme: {
        skin: "a",
        toolbars: {
            index: "ui-navigation-toolbar",
            pages: "ui-custom-toolbar"    
        }
    }

}

Nested Namespacing:
Its an extension of Object Literal notation where an object includes another object and which in turn may include another object and so on to achieve a more granular name spacing.

Ex.
var myApp =  myApp || {};

myApp.routers = myApp.routers || {};
myApp.model = myApp.model || {};
myApp.model.special = myApp.model.special || {}


Immediately Invoked Function Expressions (IIFE)s
In IIFEs  an unnamed function is immediately invoked after it’s been defined and a namespace is passed as a parameter to contained objects.

Ex.
var namespace = namespace || {};

// here a namespace object is passed as a function 
// parameter, where we assign public methods and 
// properties to it
(function( o ){    
    o.foo = "foo";
    o.bar = function(){
        return "bar";    
    };
})( namespace );

console.log( namespace );


Namespace Injection:
This is another variation on the IIFE in which we “inject” the methods and properties for a specific namespace from within a function wrapper using this as a namespace proxy 

Ex.
var myApp = myApp || {};
myApp.utils =  {};

(function () {
  var val = 5;

  this.getValue = function () {
      return val;
  };
   
  this.setValue = function( newVal ) {
      val = newVal;
  }
      
  // also introduce a new sub-namespace
  this.tools = {};
    
}).apply( myApp.utils );  

// inject new behaviour into the tools namespace
// which we defined via the utilities module

(function () {
    this.diagnose = function(){
        return "diagnosis";   
    }
}).apply( myApp.utils.tools );

Thursday, February 28, 2013

A Sample NANT Build Script with Subversion

Here is a sample NANT script which is originally referred from  Build Script in "Expert .Net Delivery", here it uses Subversion to fetch latest code from subversion which is what is different from original script.


<?xml version="1.0" encoding="utf-8" ?>
<project name="SampleTool" default="help">
<description>Build file for the SampleTool application.</description>

<property name="nant.onfailure" value="fail"/>
<property name="svnLocation" value="c:\program files\subversion\bin\svn.exe" />

     <loadtasks assembly="D:\dotNetDelivery\Tools\NAntContrib\0.85rc2\bin\NAnt.Contrib.Tasks.dll"/>
     <loadtasks assembly="D:\dotNetDelivery\Tools\NUnit2Report\1.2.2\bin\NAnt.NUnit2ReportTasks.dll"/>
<sysinfo/>

<target name="go" description="The main target for full build process execution." depends="clean, get, version1, version2, build, test, document, publish, notify"/>

<target name="clean" description="Clean up the build environment.">
<delete dir="D:\dotNetDelivery\BuildArea\Source\" failonerror="false"/>
<delete dir="D:\dotNetDelivery\BuildArea\Output\" failonerror="false"/>
<delete dir="D:\dotNetDelivery\BuildArea\Docs\" failonerror="false"/>
<delete dir="D:\dotNetDelivery\BuildArea\Reports\" failonerror="false"/>
<delete dir="D:\dotNetDelivery\BuildArea\Distribution\" failonerror="false"/>

<mkdir dir="D:\dotNetDelivery\BuildArea\Source\"/>
<mkdir dir="D:\dotNetDelivery\BuildArea\Output\"/>
<mkdir dir="D:\dotNetDelivery\BuildArea\Docs\"/>
<mkdir dir="D:\dotNetDelivery\BuildArea\Reports\"/>
<mkdir dir="D:\dotNetDelivery\BuildArea\Distribution\"/>
<mkdir dir="D:\dotNetDelivery\BuildArea\Publish\" failonerror="false"/>

</target>

<target name="get" description="Grab the source code." >
  <exec program="${svnLocation}" commandline="checkout http://some.repository.com/trunk/src/SampleTool SampleTool --username *username* --password *somepassword*"/>
 </target>


<target name="version1" description="Apply versioning to the source code files.">

<property name="sys.version" value="0.0.0.0"/>

<ifnot test="${debug}">
<version buildtype="increment" revisiontype="increment" path="SampleTool.Build.Number"/>
</ifnot>

<attrib file="D:\dotNetDelivery\BuildArea\Source\CommonAssemblyInfo.cs" readonly="false" />

<asminfo output="D:\dotNetDelivery\BuildArea\Source\CommonAssemblyInfo.cs" language="CSharp">
<imports>
<import name="System" />
<import name="System.Reflection"/>
</imports>
<attributes>
<attribute type="AssemblyVersionAttribute" value="${sys.version}" />
<attribute type="AssemblyProductAttribute" value="SampleTool" />
<attribute type="AssemblyCopyrightAttribute" value="Copyright (c) 2005, Etomic Ltd."/>
</attributes>
</asminfo>

<attrib file="D:\dotNetDelivery\BuildArea\Source\CommonAssemblyInfo.cs" readonly="true" />
</target>

<target name="version2">
<ifnot test="${debug}">
<vsslabel
user="builder"
password="builder"
dbpath="D:\dotNetDelivery\VSS\srcsafe.ini"
path="$/Solutions/SampleTool/"
comment="Automated Label"
label="NAnt - ${sys.version}"
/>
</ifnot>
</target>

<target name="build" description="Compile the application.">
<solution solutionfile="D:\dotNetDelivery\BuildArea\Source\SampleTool.sln" configuration="Debug" outputdir="D:\dotNetDelivery\BuildArea\Output\"/>
</target>

<target name="test" description="Apply the unit tests.">
<property name="nant.onfailure" value="fail.test"/>

<nunit2>
<formatter type="Xml" usefile="true" extension=".xml" outputdir="D:\dotNetDelivery\BuildArea\Reports\" />
<test assemblyname="D:\dotNetDelivery\BuildArea\Output\SampleToolTests.dll" />
</nunit2>

<nunit2report out="D:\dotNetDelivery\BuildArea\Reports\NUnit.html">
<fileset>
<include name="D:\dotNetDelivery\BuildArea\Reports\SampleToolTests.dll-results.xml" />
</fileset>
</nunit2report>

<exec program="D:\dotNetDelivery\Tools\FxCop\1.30\FxCopCmd.exe" commandline="/f:D:\dotNetDelivery\BuildArea\Output\SampleToolEngine.dll /f:D:\dotNetDelivery\BuildArea\Output\SampleToolGui.exe /o:D:\dotNetDelivery\BuildArea\Reports\fxcop.xml /r:D:\dotNetDelivery\Tools\FxCop\1.30\Rules\" failonerror="false"/>

<style style="D:\dotNetDelivery\Tools\FxCop\1.30\Xml\FxCopReport.xsl" in="D:\dotNetDelivery\BuildArea\Reports\fxcop.xml" out="D:\dotNetDelivery\BuildArea\Reports\fxcop.html"/>

<property name="nant.onfailure" value="fail"/>

</target>

<target name="document" description="Generate documentation and reports.">
<ndoc>
<assemblies basedir="D:\dotNetDelivery\BuildArea\Output\">
                <include name="SampleToolEngine.dll" />
                <include name="SampleToolGui.dll" />
            </assemblies>
            <summaries basedir="D:\dotNetDelivery\BuildArea\Output\">
                <include name="SampleToolEngine.xml" />
                <include name="SampleToolGui.xml" />
            </summaries>
            <documenters>
                <documenter name="MSDN">
                    <property name="OutputDirectory" value="D:\dotNetDelivery\BuildArea\Docs\" />
                    <property name="HtmlHelpName" value="SampleTool" />
                    <property name="HtmlHelpCompilerFilename" value="hhc.exe" />
                    <property name="IncludeFavorites" value="False" />
                    <property name="Title" value="SampleTool (NDoc)" />
                    <property name="SplitTOCs" value="False" />
                    <property name="DefaulTOC" value="" />
                    <property name="ShowVisualBasic" value="False" />
                    <property name="ShowMissingSummaries" value="True" />
                    <property name="ShowMissingRemarks" value="False" />
                    <property name="ShowMissingParams" value="True" />
                    <property name="ShowMissingReturns" value="True" />
                    <property name="ShowMissingValues" value="True" />
                    <property name="DocumentInternals" value="True" />
                    <property name="DocumentProtected" value="True" />
                    <property name="DocumentPrivates" value="False" />
                    <property name="DocumentEmptyNamespaces" value="False" />
                    <property name="IncludeAssemblyVersion" value="True" />
                    <property name="CopyrightText" value="Etomic Ltd., 2005" />
                    <property name="CopyrightHref" value="" />
                </documenter>
            </documenters>
        </ndoc>
</target>

<target name="publish" description="Place the compiled assets in agreed location.">
<copy todir="D:\dotNetDelivery\BuildArea\Distribution\">
<fileset basedir="D:\dotNetDelivery\BuildArea\Output\">
<include name="SampleToolEngine.dll"/>
<include name="SampleToolGui.exe"/>
</fileset>
</copy>

<zip zipfile="D:\dotNetDelivery\BuildArea\Publish\SampleTool-Build-${sys.version}.zip">
<fileset basedir="D:\dotNetDelivery\BuildArea\Distribution\">
<include name="**" />
</fileset>
</zip>
</target>

<target name="notify" description="Tell everyone of the success or failure.">
<echo message="Notifying you of the build process success."/>
</target>

<target name="fail">
<echo message="Notifying you of a failure in the build process."/>
</target>

<target name="fail.test">
<nunit2report out="D:\dotNetDelivery\BuildArea\Reports\NUnit.html">
<fileset>
<include name="D:\dotNetDelivery\BuildArea\Reports\SampleToolTests.dll-results.xml" />
</fileset>
</nunit2report>
</target>

<target name="help">
<echo message="The skeleton file for the build process is designed to execute the following targets in turn:"/>
<echo message="-- clean"/>
<echo message="-- get"/>
<echo message="-- version"/>
<echo message="-- build"/>
<echo message="-- test"/>
<echo message="-- document"/>
<echo message="-- publish"/>
<echo message="-- notify"/>
<echo message="This file should be run with a Boolean value for 'debug'."/>
<echo message="-- True indicates that no versioning be set (0.0.0.0)."/>
<echo message="-- False indicates that a regular version be set(1.0.x.0)."/>
<echo message="Example: -D:debug=true"/>
</target>

</project> 

Friday, February 22, 2013

Setting up NAnt on your pc/server

In this post we are going to see how to set up NANT on your PC/Server. Its first step towards Build Automation.



1.       Download Nant Binaries from http://nant.sourceforge.net/


2.       Once you download all Binary files, right click on Zip file and open Properties as show below


3.       Once properties window opens click on Unblock button as shown below



4.       Now unzip the Zipped file contents at some preferred location for eg. C:\Program Files (x86)\ Nant, as show below.




5.       Now go to “My Computer “ => “Advanced System Settings” => “Environment Variables”
And add following “System variable” as shown below


6.       Edit “Path” Variable in System Variables section as show below, append newly added system variable in your existing paths

 

7.       Open a command prompt and type “Nant – help”, you should see o/p like this.



Friday, January 11, 2013

Adapter Design Pattern

The Adapter pattern helps in Integrating 2 classes which have altogether different Interfaces. It’s useful for off-the-shelf code, for toolkits, and for libraries.  Generally Toolkit or 3rd Party controls needs a lot of adaptor classes as in many scenario it’s not possible to use Toolkit’s interfaces.

Design:
In following UML class diagram , we have a Client class and Adaptee class. Adaptee class has method “SepecificRequest” which needs to be called by Client class. Client class uses an Adaptor class which implements ITarget interface and exposes Request method. Adapter class implements Request method and it’s a child object in Client Class. So, Client doesn’t need to know anything about Adaptee class all it has to know is about ITarget interface and Request method.


Implementation:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    // Existing way requests are implemented
    class Adaptee
    {
        // Provide full precision
        public double SpecificRequest(double a, double b)
        {
            return a / b;
        }
    }

    // Required standard for requests
    interface ITarget
    {
        // Rough estimate required
        string Request(int i);
    }

    // Implementing the required standard via Adaptee
    class Adapter : Adaptee, ITarget
    {
        public string Request(int i)
        {
            return "Rough estimate is " + (int)Math.Round(SpecificRequest(i, 3));
        }
    }

    class Client
    {
        public void CallRequest()
        {
            // Showing the Adapteee in standalone mode
            Adaptee first = new Adaptee();
            Console.Write("Before the new standard\nPrecise reading: ");
            Console.WriteLine(first.SpecificRequest(5, 3));

            // What the client really wants
            ITarget second = new Adapter();
            Console.WriteLine("\nMoving to the new standard");
            Console.WriteLine(second.Request(5));
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            Client cl = new Client();
            cl.CallRequest();
            Console.Read();
        }
    }
}


Output:


Depending on their Usage, there are following 2 types of Adapter classes

1) Pluggable Adapters : Developers who recognize that their systems will need to work with other components can increase their chances of adaptation. Identifying in advance the parts of the system that might change makes it easier to plug in adapters for a variety of new situations.

Keeping down the size of an interface also increases the opportunities for new
systems to be plugged in. Although not technically different from ordinary adapters, this feature of small interfaces gives them the name pluggable adapters.
A distinguishing feature of pluggable adapters is that the name of a method called by the client and that existing in the ITarget interface can be different. The adapter must be able to handle the name change. In the previous adapter variations, this was true for all Adaptee methods, but the client had to use the names in the ITarget interface.
Suppose the client wants to use its own names, or that there is more than one client and they have different terminologies.



2) Two-Way Adapters : Adapters provide access to some behavior in the Adaptee (the behavior required in the ITarget interface), but Adapter objects are not interchangeable with Adaptee objects. They cannot be used where Adaptee objects can because they work on the implementation of the Adaptee, not its interface. Sometimes we need to have objects
that can be transparently ITarget or Adaptee objects. 

This could be easily achieved if the Adapter inherited both interfaces; however, such multiple inheritance is not possible in C#, so we must look at other solutions.

The two-way adapter addresses the problem of two systems where the characteristics of one system have to be used in the other, and vice versa. An  Adapter class is set up to absorb the important common methods of both and to provide adaptations to both. The resulting adapter objects will be Acceptable to both sides. Theoretically, this idea can be extended to more than two systems, so we can have multiway adapters, but there are some implementation limitations: without multiple inheritance, we have to insert an interface between each original class and the adapter.

Wednesday, October 10, 2012

Some Frquently Used Extension Methods

Here I am going to post some of Frequently used extension methods which can be used with a string variable


/// <summary>
        /// It formats strings into a name format.
        /// </summary>
        /// <param name="firstname"></param>
        /// <param name="middlename"></param>
        /// <param name="lastname"></param>
        /// <returns></returns>
        public static String ToName(this String firstname, string middlename, string lastname)
        {
 
            if (!string.IsNullOrEmpty(lastname))
            {
                return String.Format("{0} {1} {2}", firstname, middlename, lastname);
            }
            else
            {
                return firstname;
            }
        }
 
 
 
 
 /// <summary>
        /// It formats string into a phone format
        /// </summary>
        /// <param name="phonenumber"></param>
        /// <returns></returns>
        public static string ToPhone(this string phonenumber)
        {
            if (phonenumber == null || phonenumber.Length == 0) return null;
            long pn =
                long.Parse(
                    phonenumber.Replace(" "string.Empty).Replace(","string.Empty).Replace("("string.Empty).Replace
                        (")"string.Empty).Replace("-"string.Empty));
            if (pn == 0)
            {
                return string.Empty;
            }
            else if (pn.ToString().Length == 10)
            {
                return String.Format("{0:(000) 000-0000}", pn);
            }
            else if (pn.ToString().Length == 7)
            {
                return String.Format("{0:000-0000}", pn);
            }
            else
            {
                return string.Empty;
            }
        }
 
 
 
/// <summary>
        /// It formats a string into SSN
        /// </summary>
        /// <param name="ssn"></param>
        /// <returns></returns>
        public static string ToSSN(this string ssn)
        {
            if (ssn == null || ssn.Length == 0) return null;
            long data =
                long.Parse(
                    ssn.Replace(" "string.Empty).Replace(","string.Empty).Replace("("string.Empty).Replace(")",
                                                                                                                 string.
                                                                                                                     Empty)
                        .Replace("-"string.Empty));
            return String.Format("{0:000-00-0000}", data);
        } 



 public static bool IsValidDate(this string inStr)
        {
            bool isValidDate = false;
 
            if (inStr != null)
            {
                isValidDate = inStr.Trim().Length > 0;
                DateTime dt;
                if (isValidDate)
                {
                    isValidDate = DateTime.TryParse(inStr,out dt);
                }
            }
 
            return isValidDate;
        }
 
 
 public static string ToZipCode(this string instr)
        {
            if (instr != null)
            {
                instr = instr.PadRight(9, '0');
                return instr.Substring(0, 5) + "-" + instr.Substring(5, 4);
            }
            return string.Empty;
        }
 
 
 
 /// <summary>
        /// It formats string into ToCurrency.
        /// </summary>
        /// <param name="inStr"></param>
        /// <returns></returns>
        public static string ToCurrency(this Decimal inStr)
        {
            return String.Format(System.Globalization.CultureInfo.CreateSpecificCulture("en-us"),"{0:C}", inStr);
        } 

Tuesday, January 10, 2012

Key Architecture Principles


Consider the following key principles when designing your architecture:

  • Build to change instead of building to last. Consider how the application may need to change over time to address new requirements and challenges, and build in the flexibility to support this.
  • Model to analyze and reduce risk. Use design tools, modeling systems such as Unified Modeling Language (UML), and visualizations where appropriate to help you capture requirements and architectural and design decisions, and to analyze their impact. However, do not formalize the model to the extent that it suppresses the capability to iterate and adapt the design easily.
  • Use models and visualizations as a communication and collaboration tool. Efficient communication of the design, the decisions you make, and ongoing changes to the design, is critical to good architecture. Use models, views, and other visualizations of the architecture to communicate and share your design efficiently with all the stakeholders, and to enable rapid communication of changes to the design.
  • Identify key engineering decisions. Use the information in this guide to understand the key engineering decisions and the areas where mistakes are most often made. Invest in getting these key decisions right the first time so that the design is more flexible and less likely to be broken by changes.

Refer to (.Net Application Architecture Guide V2.0)

Monday, December 5, 2011

5 OOAD principles


1) Open Close Principle (OCP): It states that a class/module/package should be open for extension and close for modification.
2) Dependency Inversion Principle (DIP): It states that classes should not depend on concrete classes instead they should depend on abstract classes.
3) Interface Segregation Principle (ISP): It states that a class should not be needed to implement any part of any interface which it’s not going to use.
4) Singe Responsibility Principle (SRP): It states that a class should have only one responsibility.
5) Liskov’s Substitution Principle (LSP):It states that  a class a derived class should be able to completely replace base class without changing their behavior.

Saturday, December 3, 2011

Some do’s and Don’ts’s and tips on Finalize, Dispose and GC


1)      Override Finalize only when you want GC to perform cleanup for unmanaged resources.
2)      GC calls Finalize method just before reclaiming memory from that object, so you don’t have any control when Finalize method is called.
3)      Dispose method is called to cleanup managed resources and it can be called anytime when object is not needed in program by calling Dispose method.
4)      Objects which have destructor/Finalize methods take 2 steps before memory is claimed from them.
5)      If you don’t want Finalize to be called for a particular object, then call GC.SuppressFinalize for that object anytime, best place for this call would be in Dispose method. To re-register that object for Finalization you can call GC.ReRegisterForFinalize.
6)      Freachable is pronounced as F-Rechable and it means Finalizer-Reachable queue.
7)      Dispose method is not thread-safe, if your object is accessed by more than 1 thread then you should make Dispose a thread safe method.
8)      If your program uses a significant amount of unmanaged memory then you should call GC.AddMemoryPressure to make GC aware of memory chuck which was consumed by program through unmanaged way, and same way when memory is released for that unmanaged resource you can call GC.RemoveMemoryPressure .
9)      You can call GC.KeepAlive on an object when you fear that Object may be calimed by GC while its being used. This kind of scenario can occur when you have passed any object using ByRef to some unmanaged method , and that unmanaged application is using it forever.
10)   By default every application in 32 bit computer gets 2 GB of virtual address space.
11)   GC works in 2 modes which are Server and Workstation.
12)   Workstation garbage collection is always used on a computer that has only one processor, regardless of the <gcServer> setting. If you specify server garbage collection, the CLR uses workstation garbage collection with concurrency disabled.
13)   In case of Server GC mode, there is a separate dedicated thread which manages collection.
14)   Number of threads on server = Number of application * Number of processor.
15)   Since .Net 4 Non-concurrent garbage collection became Background garbage collection.
16)   Concurrent Garbage collection / Background Garbage collection is performed on Generation 2 items in Workstation mode.
17)   Background garbage collection is not currently available for server garbage collection.
18)   Background garbage collection can be defined as collection of generation 2 objects by a separated thread which is paused whenever there is foreground garbage collection happening.
19)   Concurrent garbage collection has a slightly bigger working set (compared with non-concurrent garbage collection), because you can allocate objects during concurrent collection. However, this can affect performance, because the objects that you allocate become part of your working set. Essentially, concurrent garbage collection trades some CPU and memory for shorter pauses.
20)   Background garbage collection removes allocation restrictions imposed by concurrent garbage collection, because ephemeral garbage collections can occur during background garbage collection.

21)   Finalizers should always be protected, not public or private so that the method cannot be called from the application's code directly and at the same time, it can make a call to the base.Finalize method.

22)  When an application instantiates a new object, if the object's type defines a Finalize method, a pointer to the object is placed on the finalization queue just before the type's instance constructor is called. The finalization queue is an internal data structure controlled by the garbage collector. Each entry in the list points to an object that should have its Finalize method called before the object's memory can be reclaimed.
23)  The garbage collector scans the finalization queue looking for pointers to the objects which are identified as garbage. And when found, it is moved to freachable queue which is another data structure maintained by garbage collector's internal. A special high-priority CLR thread is dedicated to calling Finalize methods and CLR uses a high priority thread to finalize these objects which appear in this freachable queue. The object in Freachable queue is reachable only to this finalization thread. So When writing the finalization method it should concentrate on disposing the local and native objects and shouldn't execute any that makes any assumptions about the thread that's executing the code.
24)   For more information on Garbage Collection please refer  http://msdn.microsoft.com/en-us/library/0xy59wtx.aspx.