Potty Little Details

Just another WordPress.com weblog

Archive for September 2008

Serializing and Deserializing… How??

leave a comment »

      To make things easier for a formatter, the Framework Class Library offers a FormatterServices type in the System.Runtime.Serialization namespace. This type has only static methods in it and no instances of the type may be instantiated. The following steps describe how a formatter automatically serializes an object whose type has the SerializableAttribute attribute applied to it:

  1. The formatter calls FormatterServices’ GetSerializableMembers method:
    public static MemberInfo[] GetSerializableMembers(Type type);
    

    This method uses reflection to get the type’s instance fields (excluding any fields marked with the NonSerializedAttribute attribute). The method returns an array of MemberInfo objects, one for each serializable instance field.

  2. The object being serialized and the array of System.Reflection.MemberInfo objects is then passed to FormatterServices’ static GetObjectData method:
    public static Object[] GetObjectData(Object obj,
        MemberInfo[] members);
    

    This method returns an array of Objects where each element identifies a field in the object being serialized. This Object array and the MemberInfo array are parallel. That is, element 0 in the Object array is the value of the member identified by element 0 in the MemberInfo array.

  3. The formatter writes the assembly’s identity and the type’s full name to the byte stream.
  4. Finally, the formatter then enumerates over the elements in the two arrays, writing each member’s name and value to the byte stream.

      The following steps describe how a formatter automatically deserializes an object whose type has the SerializableAttribute attribute applied to it.

  1. The formatter reads the assembly’s identity and full type name from the byte stream. If the assembly is not currently loaded into the AppDomain, it is loaded now (as described earlier). If the assembly can’t be loaded, a SerializationException exception is thrown and the object cannot be deserialized. If the assembly is already loaded, the formatter passes the assembly identity information and the type’s full name to FormatterServices’ static GetTypeFromAssembly method, as you can see here:
    public static Type GetTypeFromAssembly(Assembly assem,
                                           String name);
    

    This method returns a System.Type object, indicating the type of object that is being deserialized.

  2. The formatter calls FormatterServices’ static GetUninitializedObject method:
    public static Object GetUninitializedObject(Type type);
    

    This method allocates memory (all bytes are initialized to null or 0) for a new object, but does not call a constructor for the object.

  3. The formatter now constructs and initializes a MemberInfo array like it did before by calling FormatterServices’ GetSerializableMembers method. This method returns the set of fields that were serialized and that now will need to be deserialized.
  4. The formatter creates and initializes an Object array from the data contained in the byte stream.
  5. The reference to the newly allocated object, the MemberInfo array, and the parallel Object array of field values is passed to FormatterServices’ static PopulateObjectMembers method, like so:
    public static Object PopulateObjectMembers(Object obj,
        MemberInfo[] members, Object[] data);
    

    This method enumerates over the arrays, initializing each field to its corresponding value. At this point, you can be sure the object has been completely deserialized.

Advertisements

Written by oneil

September 15, 2008 at 3:23 pm

Posted in Framework

How the CLR Controls the Layout of a Type’s Fields

leave a comment »

To improve performance, the CLR is capable of arranging the fields of a type any way it
chooses. For example, the CLR might reorder fields in memory so that object references
are grouped together and data fields are properly aligned and packed. However, when
you define a type, you can tell the CLR whether it must keep the type’s fields in the
same order the developer specified them or whether it can reorder as it sees fit.
You tell the CLR what to do by applying the System.Runtime.-
InteropServices.StructLayoutAttribute attribute on the class or structure
you’re defining. To this attribute’s constructor, you can pass LayoutKind.Auto to have
the CLR arrange the fields or LayoutKind.Sequential to have the CLR preserve
your field layout. If you don’t explicitly specify the StructLayoutAttribute on a type
that you’re defining, your compiler selects whatever layout it thinks best.
You should be aware that Microsoft’s C# compiler selects LayoutKind.Auto for
reference types (classes) and LayoutKind.Sequential for value types (structures). It
is obvious that the C# compiler team feels that structures are commonly used when
interoperating with unmanaged code, and for this to work, the fields must stay in the
order defined by the programmer. However, if you’re creating a value type that has
nothing to do with interoperability with unmanaged code, you probably want to override
the C# compiler’s default. Here’s an example:
using System;
using System.Runtime.InteropService;
// Let the CLR arrange the fields to improve performance for this
// value type.
[StructLayout(LayoutKind.Auto)]
struct Point {
Int32 x, y;
}

Written by oneil

September 13, 2008 at 3:27 am

Posted in Framework

Here’s what the new operator does………….

leave a comment »

  • It allocates memory for the object by allocating the number of bytes required for the specified type from the managed heap.
  • It initializes the object’s overhead members. Every object instance has two additional members associated with the instance that the CLR uses to manage the object. The first member is the object’s pointer to the type’s method table, and the second member is a SyncBlockIndex.
  • The type’s instance constructor is called, passing it any parameters (the string “ConstructorParam1″, in the preceding example) specified in the call to new. Although most languages compile constructors so that they call the base type’s constructor, the CLR doesn’t require this call.
  • After new has performed all these operations, it returns a reference to the newly created
    object.

Written by oneil

September 13, 2008 at 3:23 am

Posted in Framework

How Common Language Runtime gets loaded

with one comment

When the compiler/linker creates an executable assembly, the following 6-byte x86 stub
function is emitted into the PE file’s .text section:
JMP _CorExeMain
Because the _CorExeMain function is imported from Microsoft’s MSCorEE.dll dynamic-link library, MSCorEE.dll is referenced in the assembly file’s import (.idata) section. MSCorEE.dll stands for Microsoft Component Object Runtime Execution Engine. When the managed EXE file is invoked, Windows treats it just like any normal (unmanaged) EXE file: the Windows loader loads the file and examines the .idata section to see that MSCorEE.dll should be loaded into the process’s address space. Then the loader obtains the address of the _CorExeMain function inside MSCorEE.dll and fixes up the stub function’s JMP instruction
in the managed EXE file. The process’s primary thread begins executing this x86 stub function, which immediately jumps to _CorExeMain in MSCorEE.dll. _CorExeMain initializes the CLR and then looks at
the executable assembly’s CLR header to determine what managed entry point method should execute. The IL code for the method is then compiled into native CPU instructions, and the CLR jumps to the native code (using the process’s primary thread). At this point, the managed application’s code is running. The situation is similar for a managed DLL. When building a managed DLL, the compiler/linker emits a similar 6-byte x86 stub function in the PE file’s .text section for a DLL assembly:
JMP _CorDllMain
The _CorDllMain function is also imported from the MSCorEE.dll, causing the DLL’s .idata section to reference MSCorEE.dll. When Windows loads the DLL, it will automatically load MSCorEE.dll (if it isn’t already loaded), obtain the address of the _CorDllMain function, and fix up the 6-byte x86 JMP stub in the managed DLL. The thread that called LoadLibrary to load the managed DLL now jumps to the x86 stub in the managed DLL assembly, which immediately jumps to the _CorDllMain function in MSCorEE.dll. _CorDllMain initializes the CLR (if it hasn’t already been initialized for the process) and then returns so that the application can continue executing as normal.These 6-byte x86 stub functions are required to run managed assemblies on Windows 98,Windows 98 Standard Edition, Windows Me, Windows NT 4, and Windows 2000 because all
these operating systems shipped long before the CLR became available. Note that the 6-byte stub function is specifically for x86 machines. This stub doesn’t work properly if the CLR is ported to run on other CPU architectures. Because Windows XP and the Windows .NET Server Family support both the x86 and the IA64 CPU architectures, Windows XP and the Windows .NET Server Family loader was modified to look specifically for managed assemblies. On Windows XP and the Windows .NET Server Family, when a managed assembly is
invoked (typically via CreateProcess or LoadLibrary), the OS loader detects that the file contains managed code by examining directory entry 14 in the PE file header. (See IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR in WinNT.h.) If this directory entry exists and is not 0, the loader ignores the file’s import (.idata) section and automatically loads MSCorEE.dll into the process’s address space. Once loaded, the OS loader makes the process’s thread jump directly to the correct function in MSCorEE.dll. The 6-byte x86 stub functions are ignored on machines running Windows XP and the Windows .NET Server Family.
One last note on managed PE files: they always use the 32 bit PE file format, not the 64-bit PE file format. On 64-bit Windows systems, the OS loader detects the managed 32-bit PE file and automatically knows to create a 64-bit address space.(More on Programming Dot net Jeffery Ritcher)

Written by oneil

September 13, 2008 at 2:38 am

Posted in Framework

Demystifying Delegates

leave a comment »

On the surface, delegates seem easy to use: you define them using C#’s delegate keyword, you construct instances of them using the familiar new operator, and you invoke the callback using familiar “method call” syntax (except instead of a method name, you use the variable that refers to the delegate object).However, what’s really going on is quite a bit more complex . The compilers and the common language runtime (CLR) do a lot of behind-thescenes processing to hide the complexity. In this section, I’ll focus on how the compiler and the CLR work together to implement delegates.

Let’s start by reexamining this line of code:

public delegate void Feedback(

Object value, Int32 item, Int32 numItems);

When it sees this line, the compiler actually defines a complete class definition that lookssomething like this:

public class Feedback : System.MulticastDelegate {

// Constructor

public Feedback(Object target, Int32 methodPtr);

// Method with same prototype as specified by the source code

public void virtual Invoke(

Object value, Int32 item, Int32 numItems);

// Methods allowing the callback to be called asynchronously

public virtual IAsyncResult BeginInvoke(

Object value, Int32 item, Int32 numItems,

AsyncCallback callback, Object object);

public virtual void EndInvoke(IAsyncResult result);

}

The class defined by the compiler has four methods: a constructor, Invoke, BeginInvoke, and EndInvoke.In fact, you can verify that the compiler did indeed generate this class automatically by examining the resulting module with ILDasm.exe.In this example, the compiler has defined a class called Feedback that is derived from the System.MulticastDelegate type defined in the .NET Framework Class Library (FCL).(All delegate types are derived from MulticastDelegate.) The class is public because the delegate is declared as public in the source code. If the source code had indicated private or protected, the Feedback class the compiler generated would also be private or protected, respectively. You should be aware that delegate types can be defined within a class (as in the example, Feedback is defined within the Set class) or at global scope.Basically, because delegates are classes, a delegate can be defined anywhere a class can be defined.Because all delegate types are derived from MulticastDelegate, they inherit MulticastDelegate’s fields, properties, and methods. Of all these members, three private fields are probably most significant.

Field Type Description

_target System.Object Refers to the object that should be operated on when the callback method is called.This field is used for instance method callbacks.

_methodPtr System.Int32 An internal integer that the CLR uses to identify the method that is to be called back.

_prev System.MulticastDelegate Refers to another delegate object. This field is usually null.

Notice that all delegates have a constructor that takes two parameters: a reference to an object and an integer that refers to the callback method.A reference to the object is passed for the target parameter, and a special Int32 value (obtained from a MethodDef or MethodRef metadata token) that identifies the method is passed for the methodPtr parameter. For static methods, null is passed for the target parameter.Inside the constructor, these two parameters are saved in their corresponding private fields.In addition, the constructor sets the _prev field to null. This _prev field is used to create a linked list of MulticastDelegate objects.So, each delegate object is really a wrapper around a method and an object to be operated on when the method is called. The MulticastDelegate class defines two read-only public instance properties: Target and Method. Given a reference to a delegate object, you can query these properties. The Target property returns a reference to the object that will be operated on if the method is called back. If the method is a static method, Target returns null. The Method property returns a System.Reflection.MethodInfo object thatidentifies the callback method.You could use this information in several ways. For example, you could check to see whether a delegate object refers to an instance method of a specific type:

Boolean DelegateRefersToInstanceMethodOfType(

MulticastDelegate d, Type type) {

return((d.Target != null) && d.Target.GetType() == type);

}

You could also write code to check whether the callback method has a specific name (such as FeedbackToMsgBox):

Boolean DelegateRefersToMethodOfName(

MulticastDelegate d, String methodName) {

return(d.Method.Name == methodName);

}

Now that you know how delegate objects are constructed, let’s talk about how the callback method is invoked.

public void ProcessItems(Feedback feedback) {

for (Int32 item = 0; item < items.Length; item++) {

if (feedback != null) {

// If any callbacks are specified, call them.

feedback(items[item], item, items.Length);

}

}

}

Just below the comment is the line of code that invokes the callback method. It might seem as if I’m calling a function named feedback and passing it three parameters. However,there is no function called feedback. Again, because it knows that feedback is a variable that refers to a delegate object, the compiler generates code to call the delegate object’s Invoke method. In other words, the compiler sees this:

feedback(items[item], item, items.Length);

But the compiler generates code as though the source code said this:

feedback.Invoke(items[item], item, items.Length);

You can verify that the compiler produces code to call the delegate type’s In-voke method by using ILDasm.exe to examine the code for the ProcessItems method. More details check out dot net programming by Jeffery Ritcher

Written by oneil

September 13, 2008 at 2:24 am

Posted in C#

Obtaining BLOB Values from a Database [C#]

leave a comment »

The default behavior of the DataReader is to load incoming data as a row as soon as an entire row of data is available. Binary large objects, or BLOBs, need to be treated differently, however, because they can contain gigabytes of data that cannot be contained in a single row. The Command.ExecuteReader method has an overload which will take a CommandBehavior argument to modify the default behavior of the DataReader. You can pass CommandBehavior.SequentialAccess to the ExecuteReader method to modify the default behavior of the DataReader so that instead of loading rows of data, it will load data sequentially as it is received. This is ideal for loading BLOBs or other large data structures.

When setting the DataReader to use SequentialAccess, it is important to note the sequence in which you access the fields returned. The default behavior of the DataReader, which loads an entire row as soon as it is available, allows you to access the fields returned in any order until the next row is read. When using SequentialAccess however, you must access the different fields returned by the DataReader in order. For example, if your query returns three columns, the third of which is a BLOB, you must return the values of the first and second fields before accessing the BLOB data in the third field. If you access the third field before the first or second fields, the first and second field values will no longer be available. This is because SequentialAccess has modified the DataReader to return data in sequence and the data will not be available after the DataReader has read past it.

When accessing the data in the BLOB field, use the GetBytes typed accessor of the DataReader, which fills a byte array with the binary data. You can specify a specific buffer size of data to be returned, and a starting location for the first byte read from the returned data. GetBytes will return a long value, which represents the number of bytes returned. If you pass a null byte array to GetBytes, the long value returned will be the total number of bytes in the BLOB. You can optionally specify an index in the byte array as a start position for the data being read.

The following example returns the publisher id and logo from the pubs sample database in Microsoft SQL Server. The publisher id (pub_id) is a character field, and the logo is an image, which is a BLOB. Notice that the publisher id is accessed for the current row of data before the logo, because the fields must be accessed sequentially.

SqlConnection pubsConn = new SqlConnection(“Data Source=localhost;Integrated Security=SSPI;Initial Catalog=pubs;”);

SqlCommand logoCMD = new SqlCommand(“SELECT pub_id, logo FROM pub_info”, pubsConn);

FileStream fs; // Writes the BLOB to a file (*.bmp).

BinaryWriter bw; // Streams the BLOB to the FileStream object.

int bufferSize = 100; // Size of the BLOB buffer.

byte[] outbyte = new byte[bufferSize]; // The BLOB byte[] buffer to be filled by GetBytes.

long retval; // The bytes returned from GetBytes.

long startIndex = 0; // The starting position in the BLOB output.

string pub_id = “”; // The publisher id to use in the file name.

// Open the connection and read data into the DataReader.

pubsConn.Open();

SqlDataReader myReader = logoCMD.ExecuteReader(CommandBehavior.SequentialAccess);

while (myReader.Read())

{

// Get the publisher id, which must occur before getting the logo.

pub_id = myReader.GetString(0);

// Create a file to hold the output.

fs = new FileStream(“logo” + pub_id + “.bmp”, FileMode.OpenOrCreate, FileAccess.Write);

bw = new BinaryWriter(fs);

// Reset the starting byte for the new BLOB.

startIndex = 0;

// Read the bytes into outbyte[] and retain the number of bytes returned.

retval = myReader.GetBytes(1, startIndex, outbyte, 0, bufferSize);

// Continue reading and writing while there are bytes beyond the size of the buffer.

while (retval == bufferSize)

{

bw.Write(outbyte);

bw.Flush();

// Reposition the start index to the end of the last buffer and fill the buffer.

startIndex+= bufferSize;

retval = myReader.GetBytes(1, startIndex, outbyte, 0, bufferSize);

}

// Write the remaining buffer.

bw.Write(outbyte);

bw.Flush();

// Close the output file.

bw.Close();

fs.Close();

}

// Close the reader and the connection.

myReader.Close();

pubsConn.Close();

Written by oneil

September 11, 2008 at 3:01 am

Posted in ADO dot net

Working with Connection Events [C#]

leave a comment »

The Connection object has two events you can use to retrieve informational messages from a data source or to determine if the state of a Connection has changed. The following table lists the events of the Connection object.

Event

Description

InfoMessage

Occurs when an informational message is returned from a data source. Informational messages are messages from a data source that do not result in an exception being thrown.

StateChange

Occurs when the state of the Connection changes.

InfoMessage

You can retrieve warnings and informational messages from a data source using the InfoMessage event of the Connection object. Errors returned from the data source result in an exception being thrown. However, the InfoMessage event can be used to obtain messages from the data source that are not associated with an error. In the case of Microsoft SQL Server, any message with a severity of 10 or less is considered informational and would be captured using the InfoMessage event.

The InfoMessage event receives an InfoMessageEventArgs object containing, in its Errors property, a collection of the messages from the data source. You can query the Error objects in this collection for the error number and message text, as well as the source of the error. The SQL Server .NET Data Provider also includes detail about the database, stored procedure, and line number that the message came from.

The following code example shows how to add an event handler for the InfoMessage event.

SqlConnection nwindConn = new SqlConnection(“Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind;”);

nwindConn.InfoMessage += new SqlInfoMessageEventHandler(OnInfoMessage);

protected static void OnInfoMessage(object sender, SqlInfoMessageEventArgs args)

{

foreach (SqlError err in args.Errors)

{

Console.WriteLine(“The {0} has received a severity {1}, state {2} error number {3}\n” +

“on line {4} of procedure {5} on server {6}:\n{7}”,

err.Source, err.Class, err.State, err.Number, err.LineNumber,

err.Procedure, err.Server, err.Message);

}

}

StateChange

The StateChange event occurs when the state of a Connection changes. The StateChange event receives StateChangeEventArgs that enable you to determine the change in state of the Connection using the OriginalState and CurrentState properties. The OriginalState property is a ConnectionState enumeration that indicates the state of the Connection before it changed. CurrentState is a ConnectionState enum that indicates the state of the Connection after it changed.

The following code example uses the StateChange event to write a message to the console when the state of the Connection changes.

nwindConn.StateChange += new StateChangeEventHandler(OnStateChange);

protected static void OnStateChange(object sender, StateChangeEventArgs args)

{

Console.WriteLine(“The current Connection state has changed from {0} to {1}.”,

args.OriginalState, args.CurrentState);

}

Written by oneil

September 11, 2008 at 2:59 am

Posted in ADO dot net