Pages

Monday, September 12, 2005

Convert Custom Objects in XML Data Using Reflection

//Created By Kaushal
public string ConvertToXML()
{


//output will used to store parent object's xml representation

StringBuilder output = new StringBuilder();

//output will used to store child object's xml representation

StringBuilder refOutput = new StringBuilder();

//I am considering Object Node is Root Node..


output.Append("");

//Getting Count of parent Objects

for (int i=0;i<=this.Count-1;i++)
{

//Getting Properties Info using Reflection

PropertyInfo[] objFields = this.List[i].GetType().GetProperties();

//Adding Reflected Object Type in to XML String as Parent Node of an Entity as Node Name

output.Append("<" + objFields[0].ReflectedType.Name.ToString() + ">");

//Appending Data as seprate Attribute in the node

output.Append("<" + objFields[0].ReflectedType.Name.ToString());

// Accessing each property

foreach(PropertyInfo prop in objFields)
{

//Checking that the current property is Readable or not

if (prop.CanRead)
{

//If yes then checking the return type of the property. If its Value Type or Normal String I am handling it in the ELSE part.

if ((!prop.PropertyType.IsValueType) && (prop.PropertyType !=typeof(System.String)) && (prop.PropertyType !=typeof(Framework.CError)) )

{
//Getting Value from Reflected Object
object oCustomObject = prop.GetValue(this[i] as object,null);

//Appending object's value into XML

if (null!=oCustomObject)
{
//if object type is ref. type then it will go for recursion call in the next private function.

refOutput.Append(ConvertToXML(oCustomObject));
}
else
{
//Getting data of property in case of value type or String
Object strObjectString = prop.GetValue(this.List[i] as object,null);

if (null!=strObjectString)
{
output.Append(" " + prop.Name.ToString() + "='");
output.Append(strObjectString.ToString()+ "'");
}
}
}
}
output.Append("/>");
output.Append(refOutput.ToString());
refOutput.Remove(0,refOutput.Length);
output.Append(" output = output.Replace("Key","ID");
}
output.Append("");
return output.ToString();
}

//Created By Kaushal
private string ConvertToXML(object oUserObject)
{

StringBuilder output = new StringBuilder();
StringBuilder refOutput = new StringBuilder();
Type objectType = oUserObject.GetType().BaseType;
int iCount = objectType==typeof(System.Object)? 1 : (oUserObject as EntityCollectionBase).Count;
output.Append(objectType==typeof(System.Object)? "<" + oUserObject.GetType().Name + ">" : "");

for (int i=0;i<=iCount-1;i++)
{
PropertyInfo[] objFields = objectType==typeof(System.Object)? oUserObject.GetType().GetProperties() : (oUserObject as EntityCollectionBase)[i].GetType().GetProperties();
Object oTmpObject = objectType==typeof(System.Object)? oUserObject : (oUserObject as EntityCollectionBase)[i] as object;
output.Append("<" + objFields[0].ReflectedType.Name.ToString() + ">");
output.Append("<" + objFields[0].ReflectedType.Name.ToString());

foreach(PropertyInfo prop in objFields)
{
if (prop.CanRead)
{
if ((!prop.PropertyType.IsValueType) && (prop.PropertyType !=typeof(System.String)) && (prop.PropertyType !=typeof(Framework.CError)) )
{
object oCustomObject = prop.GetValue(oTmpObject as object,null) as object;
if (null!=oCustomObject)
//Making Nested Calls
refOutput.Append(ConvertToXML(oCustomObject));
}
else
{
Object strObjectString = prop.GetValue(oTmpObject,null);
if (null!=strObjectString)
{
output.Append(" " + prop.Name.ToString() + "='");
output.Append(strObjectString.ToString()+ "'");
}
}
}
}
output.Append("/>");
output.Append(refOutput.ToString());
refOutput.Remove(0,refOutput.Length);
output.Append("
output = output.Replace("Key","ID");
}

output.Append(objectType==typeof(System.Object)? "return output.ToString();

}


4 More Details Mail me @ mail2kaushal@gmail.com

Thursday, September 08, 2005

Generate Property Classes On Fly : Kaushal Patel

Class Used : PropertyBuilder [PropertyBuilder Class defines the properties for a type.]

Code :


using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;


class PropertyBuilderDemo
{
public static Type BuildProperties()
{
AppDomain _Domain = Thread.GetDomain();
AssemblyName _AssemblyName = new AssemblyName();
_AssemblyName.Name = "DynamicAssembly";

AssemblyBuilder _AssemblyBuilder = _Domain.DefineDynamicAssembly(_AssemblyName,AssemblyBuilderAccess.RunAndSave);

ModuleBuilder _ModuleBuilder = _AssemblyBuilder.DefineDynamicModule("DynamicModule");
TypeBuilder _TypeBuilder = _ModuleBuilder.DefineType("CustomerData",TypeAttributes.Public);
FieldBuilder _customerName = _TypeBuilder.DefineField("_CustomerName",typeof(string),FieldAttributes.Private);
PropertyBuilder _CustomerName = _TypeBuilder.DefineProperty("CustomerName",PropertyAttributes.HasDefault,typeof(string),new Type[] { typeof(string) });
//Assigning 'Get' Behavior to Customer Name Property

MethodBuilder _GetCustomerName = _TypeBuilder.DefineMethod("GetCustomerName",MethodAttributes.Public,typeof(string),new Type[] { });

ILGenerator _GetILGenerator = _GetCustomerName.GetILGenerator();
_GetILGenerator.Emit(OpCodes.Ldarg_0);
_GetILGenerator.Emit(OpCodes.Ldfld,_customerName);
_GetILGenerator.Emit(OpCodes.Ret);
//Assigning 'Set' Behavior to Customer Name Property
MethodBuilder _SetCustomerName = _TypeBuilder.DefineMethod("SetCustomerName",MethodAttributes.Public,null,new Type[] { typeof(string) });

ILGenerator _SetILGenerator = _SetCustomerName.GetILGenerator();
_SetILGenerator.Emit(OpCodes.Ldarg_0);
_SetILGenerator.Emit(OpCodes.Ldarg_1);
_SetILGenerator.Emit(OpCodes.Stfld,_customerName);
_SetILGenerator.Emit(OpCodes.Ret);
//Attaching Get and Set behaviors to property
_CustomerName.SetGetMethod(_GetCustomerName);
_CustomerName.SetSetMethod(_SetCustomerName);

return _TypeBuilder.CreateType();
}
}


///Client Code

static void Main(string[] args)
{
Type customer = PropertyBuilderDemo.BuildProperties();
PropertyInfo[] properties = customer.GetProperties();
object customerData = Activator.CreateInstance(customer);
properties[0].SetValue(customerData,"CREATED BY : Kaushal Patel",BindingFlags.SetProperty,null,null,null);
string s = properties[0].GetValue(customerData,BindingFlags.GetProperty,null,null,null).ToString();
Console.WriteLine(s.ToString());
Console.ReadLine();
}

4 More Information Do Mail Me @ mail2kaushal@gmail.com

Tuesday, September 06, 2005

The Importance of Using Managed Code in .NET

Introduction


What is managed code and why is it important to use 100% managed
code in .NET applications?



Managed code is compiled for the .NET run-time environment. It
runs in the Common Language Runtime (CLR), which is the heart of
the .NET Framework. The CLR provides services such as security,
memory management, and cross-language integration. (3) Managed
applications written to take advantage of the features of the CLR
perform more efficiently



and safely, and take better advantage of developers’
existing expertise in languages that support the .NET
Framework.



Unmanaged code includes all code written before the .NET
Framework was introduced—this includes code written to use
COM, native Win32, and Visual Basic 6. Because it does not run
inside the .NET environment, unmanaged



code cannot make use of any .NET managed facilities. (1)



Advantages of Using Managed Code


Managed code runs entirely “inside the sandbox,”
meaning that it makes no



calls outside of the .NET Framework. That’s why managed
code gets the



maximum benefit from the features of the .NET Framework, and
why



applications built with managed code perform more safely and
efficiently.



Performance


The CLR was designed from the start to provide good performance.
By using 100% managed code, you can take advantage of the numerous
built-in services of the CLR to enhance the
performance of your managed



application. Because of the runtime services and checks that the
CLR performs, applications do not need to include separate versions
of these services. (9) And by using 100% managed code, you
eliminate the



performance costs associated with calling unmanaged code.



Just-In-Time compiler


The CLR never executes Common Intermediate Language (CIL)
directly.



Instead, the Just-In-Time (JIT) compiler translates CIL into
optimized x86



native instructions. (9) That’s why using managed code
lets your software run



in different environments safely and efficiently. In addition,
using machine



language lets you take full advantage of the features of the
processor the




application is running on. For example, when the JIT encounters
an Intel



processor, the code produced takes advantage of
hyper-threading



technology. (5)



Another advantage of the JIT is improved performance. The JIT
learns when



the code
does multiple iterations. The runtime is designed to be able to



retune the JIT compiled code as your program runs. (2)



NGEN utility


NGEN.exe is a .NET utility that pre-compiles the application at
install time.



Pre-compiling improves start-up performance for managed code,
especially



when the application uses Windows Forms. Methods are JITed when
they



are first used, incurring a larger startup penalty if the
application calls many



methods during start-up. Because Windows Forms uses many
shared



libraries in the operating system, pre-compiling Windows Forms
applications



usually improves performance. (12)



Pre-compiling also makes sure that the application is optimized
for the



machine on which it is being installed.



Maintaining a 100% managed code environment


Only when your .NET application uses components that are built
using 100%



managed code do you receive the full benefits of the .NET
environment.



For example, when accessing data through ADO.NET, using wire
protocol


.NET data providers lets you preserve your managed code
environment



because they do not make calls to native Win32 APIs and Client
pieces.



The performance advantages of the managed code environment are
lost



when you (or the components you are using) call unmanaged code.
The CLR



makes additional checks on calls to the unmanaged or native
code, which



impacts performance.



Unmanaged code includes the database client pieces that some
.NET data



providers require. Examples of .NET data providers that use both
managed



and unmanaged code are IBM’s DB2 data provider and the
Oracle Data



Provider for .NET (ODP.NET). Both of these data providers must
use client



libraries to access the database. The data providers shipped
Microsoft for



SQL Server and Oracle—as well as the Microsoft OLE DB data
providers,



and ODBC.NET—make calls to native Win32 database client
pieces or other



unmanaged code.



Automatic memory management


Automatic memory management is one of the most significant
features of



managed code. The CLR garbage collector automatically frees
allocated



objects when there are no longer any outstanding references to
them. The



developer does not need to explicitly free memory assigned to an
object,



which goes a long way toward reducing the amount of time spent
debugging



memory leaks. (10) There can be no memory leaks in 100% managed
code.




Automatic lifetime control of objects


Another significant advantage of using managed code is that the
CLR



provides automatic lifetime management of components and
modules.



Lifetime control includes:



• Garbage collection, which frees and compacts
memory.



• Scalability features, such as thread pooling
and the ability to use a nonpersistent



connection with a dataset.



• Support for side-by-side versions.



Garbage collection


When an object is created with the new operator,
the runtime allocates



memory from the managed heap. Periodically, the CLR garbage
collector



checks the heap and automatically disposes of any objects that
are no longer



being used by the application, reclaiming their memory.



The garbage collector also compacts the released memory,
reducing



fragmentation. (4) This function is particularly important when
the application



runs on large memory servers. Changing the application to use
smaller



objects can help to improve the effectiveness of the garbage
collector.



Similarly, because each DLL is assigned a 64-bit chunk of
memory,



combining small DLLs avoids inefficient use of memory.



Because the garbage collector automatically closes unused
objects, memory



leaks are not possible in an application that uses 100% managed
code.



Scalability features


Thread pooling lets you make much more efficient use of multiple
threads



and is an important scalability feature of using managed code.
The .NET



Framework comes with built-in support for creating threads and
using the



system-provided thread pool. In particular, the ThreadPool class
under the



System.Threading namespace provides static methods for
submitting



requests to the thread pool. In managed code, if one of the
threads becomes



idle, the thread pool injects another worker thread into the
multithread



apartment to keep all the processors busy.



The standard ThreadPool methods capture the caller’s stack
and merge it



into the stack of the thread-pool thread when the thread-pool
thread starts to



execute a task. If you are using unmanaged code, the entire
stack will be



checked, which incurs a performance cost. In some cases, you can
eliminate



the stack checking with the Unsafe methods



ThreadPool.UnsafeQueueUserWorkItem and



ThreadPool.UnsafeRegisterWaitForSingleObject, which provide
better



performance. However, using the Unsafe method calls does not
provide



complete safety. (8)



Further adding to scalability is the ability to use a
non-persistent connection



with a dataset, which is a cache of the records retrieved from
the database.



The dataset keeps track of the state of the data and stores the
data as pure



XML. Database connections are opened and closed only as needed
to



retrieve data into the dataset, or to return updated data.
(7)



Versioning


Versioning essentially eliminates “DLL hell.” When
you define an assembly as



strongly named, the .NET executable will be executed with the
same DLL



with which it was built. This means that you can have
side-by-side versions of



a DLL, allowing you to manage shared components. Versioning
ensures that



each time an application starts up, it checks its shared files.
If a file has



changed and the changes are incompatible, the application can
ask the



runtime for a compatible version.



However, when an application calls unmanaged DLLs, you can end
up back



in “DLL hell.” For example, Oracle’s ODP.NET
data provider calls the



unmanaged Oracle Client pieces, which are specific to a
particular version of



Oracle. You could install two versions of this unmanaged
data provider, for



example, one for Oracle9i and one for the upcoming Oracle10G,
but you



would have a conflict, because each data provider will require a
particular



version of the clients. Since the clients are native Win32 DLLs,
you cannot



easily have side-by-side versions running on the same machine.
Only with



native wire protocol data providers built from 100% managed code
can you



install side-by-side versions with no configuration required by
the end-user.



Checks by the .NET runtime


The .NET runtime automatically performs numerous checks to
ensure that



code is written correctly. Because these checks prevent a large
number of



bugs from ever happening, developer productivity is improved and
the



application quality is better. In addition, these checks thwart
system attacks



such as the exploitation of buffer overruns.



The CLR checks for type safety to ensure that applications
always access



allocated objects in appropriate ways. In other words, if a
method input



parameter is declared as accepting a 4-byte value, the common
language



runtime will detect and trap attempts to access the parameter as
an 8-byte



value. Type safety also means that execution flow will only
transfer to known



method entry points. There is no way to construct an arbitrary
reference to a



memory location and cause code at that location to begin
execution.



In addition, array indexes are checked to be sure they are in
the range of the



array. For example, if an object occupies 10 bytes in memory,
the application



can’t change the object so that it will allow more than 10
bytes to be read.



(11)



Cross-language integration


You can write .NET applications in many different languages,
such as C,



C++, Visual Basic, COBOL, Fortran, Perl, Pascal, Jscript, Lisp,
Python,



Smalltalk, and others. Programmers can use the languages that
they are



most proficient with to develop portions of an application.




All CLR-compliant languages compile to Common Intermediate
Language



(CIL). CIL is the key to making the .NET application
platform-neutral and



hardware independent.



In addition, programmers can choose specific languages for
specific tasks



within the same application. Some languages are stronger than
others for



particular tasks, and programmers can choose the language best
suited for



the task. The originating language doesn’t matter, because
all .NETcompliant



compilers produce CIL.



Platform-neutrality


A managed .NET application can execute on any Windows platform
that



supports the .NET common language runtime. Currently, these
platforms are



Windows 98, Windows 2000, Windows Me, Windows NT, Windows XP,
and



Windows Server 2003 (32-bit). Support for the .NET Framework
and



Common Language Runtime on Windows Server 2003 (64-bit) is
planned for



an upcoming release.



In addition, with the Microsoft Mobile Internet Toolkit,
developers can create a



.NET compliant, mobile Web application that can be adapted to
the display of



multiple wireless devices. (6)



Security


Managed code does not have direct access to memory, machine
registers, or



pointers. The .NET Framework security enforces security
restrictions on



managed code that protects the code and data from being misused
or



damaged by other code. An administrator can define a security
policy to grant



or revoke permissions on an enterprise, a machine, an assembly,
or a user



level. For these reasons, applications that use managed code are
much



safer.



Code access security


Code access security lets the administrator specify which
operations a piece



of code can perform, stopping inappropriate behavior before it
can start. You



can configure a complex set of rules to:



Specify whether a code group can both read and write files



Demand that the code’s callers have specific
permissions



Allow only callers from a particular organization or site to
call the code



Grant permissions to each assembly that is loaded



Compare the granted permissions
of every caller on the call stack at



runtime to the permissions that callers must have and which
resources the



code can access. (6)



The access privileges an administrator assigns depend in part on
where the



application is running. For example, by default, an application
that runs from



the local computer has a higher level of trust and more
privileges, such as



accessing the file system, than an application that is running
from the



Internet.



Calling unmanaged code bypasses the .NET CLR security. An
application



that calls unmanaged code doesn’t necessarily have a
security problem—it



simply has an open door to the possibility of problems due to
the functionality



of the unmanaged code that has direct access to memory or
machine



registers, or uses pointers. Once the unmanaged code is being
executed, the



CLR can no longer check it.



Avoiding buffer overruns


One common type of attack attempts to make API methods operate
out of



specification, causing a buffer overrun. This attack typically
passes



unexpected parameters, such as an out-of-range index or offset
value.



Managed code avoids the buffer overruns that trigger so many
security



snafus.



Buffer overruns usually occur in programs written in languages
such as C or



C++, which do not check array bounds and type safety. If an
application does



not check the validity of the destination buffer size and other
parameters, the



copied data might overrun the buffer, overwriting the data in
adjacent



addresses.



Buffer overruns are theoretically impossible in managed
code.



Summary


Using 100% managed code gives you solid performance, improved
security,



and fewer bugs. The CLR provides memory management and lifetime
control



of objects, including scalability features and versioning. When
you call



unmanaged code, you lose many of the valuable benefits of the
.NET



environment.



References


1.
Gentile, Sam. “Intro to Managed C++, Part 2: Mixing Managed
and



Unmanaged Code.” The O’Reilly Network.




http://www.ondotnet.com/lpt/a/3226
<08/20/2003>



2. Gray, Jan. “Writing Faster
Managed Code: Know What Things Cost.”



MSDN Library. http://msdn.microsoft.com/library/?url=/library/enus/


dndotnet/html/fastmanagedcode.asp
<08/20/2003>



3. Gregory, Kate. “Managed,
Unmanaged, Native: What Kind of Code Is



This?” http://www.developer.com/net/cplus/print.php/2197621


<08/20/2003>



4.
Mariani, Rico. “Garbage Collector Basics and Performance
Hints.” MSDN



Library. April 2003.




http://msdn.microsoft.com/library/default.asp?url=/library/enus/



dndotnet/html/dotnetgcbasics.asp
<08/20/2003>



5. McNaughton, Allan. “Boosting
the Performance of Microsoft .NET.” MSDN



Library.
http://msdn.microsoft.com/library/default.asp?url=/library/enus/


dndotnet/html/optimaldotnet.asp
<08/20/2003>



6. Microsoft Corporation.
“Deployment Guide for the Microsoft Mobile Internet



Toolkit.”
http://msdn.microsoft.com/library/default.asp?url=/library/enus/


dnmitta/html/deploymobilwebapp.asp?frame=true
<08/20/2003>



7. Microsoft. “The Windows
Server 2003 Application Environment.” MSDN



Library.
http://msdn.microsoft.com/library/default.asp?url=/library/enus/


dnnetserv/html/windowsnetserver.asp
<08/20/2003>



8.
Microsoft. .NET Framework Developer’s Guide .
Microsoft .NET Framework



SDK1.0. 2001.



9. Noriskin, Gregor. “Writing
High-Performance Managed Applications: A



Primer.” MSDN Library.




http://msdn.microsoft.com/library/default.asp?url=/library/enus/



dndotnet/html/optimaldotnet.asp
<08/04/2003>



10. Platt, David S. Introducing Microsoft .NET .
Microsoft Press. Redmond, WA.



2001.



11. Richter,
Jeffrey. “Microsoft .NET Framework Delivers the Platform for
an



Integrated, Service-Oriented Web.” MSDN Magazine .





http://msdn.microsoft.com/msdnmag/issues/0900/Framework/default.aspx



<08/20/2003>



12. Schanzer, Emmanuel. “Performance Tips and Tricks in
.NET Applications.”



MSDN Library.
http://msdn.microsoft.com/library/default.asp?url=/library/enus/

Sunday, September 04, 2005

Whidbey And Partial Classes : Kaushal Patel

One of the language enhancements in .NET 2.0—available in both VB.NET 2005 and C# 2.0—is support for partial classes. In a nutshell, partial classes mean that your class definition can be split into multiple physical files. Logically, partial classes do not make any difference to the compiler. During compile time, it simply groups all the various partial classes and treats them as a single entity.

One of the greatest benefits of partial classes is that it allows a clean separation of business logic and the user interface (in particular the code that is generated by the visual designer). Using partial classes, the UI code can be hidden from the developer, who usually has no need to access it anyway. Partial classes will also make debugging easier, as the code is partitioned into separate files.

In this article, I will examine the use of partial classes in more detail and discuss how Visual Studio 2005 makes use of partial classes.

Using Partial Classes
Listing 1 contains two class definitions written in VB.NET, with the second class definition starting with the partial keyword. Both class definitions may reside in two different physical files. Functionally, Listing 1 is equivalent to Listing 2.

Listing 1
'---File1.vb---
Public Class Class1
Public Sub method1()

End Sub
End Class

File2.vb
Partial Public Class Class1
Public Sub method2()

End Sub
End Class
Listing 2
'---File1.vb---
Public Class Class1
Public Sub method1()

End Sub
Public Sub method2()

End Sub
End Class

So, what are the uses for partial classes?

Here are some good reasons to use partial classes:
They allow programmers on your team to work on different parts of a class without needing to share the same physical file. While this is useful for projects that involve big class files, be wary: If you find your class file getting too large, it may well signal a design fault and refactoring may be required.
The most compelling reason for using partial class is to separate your application business logic from the designer-generated code. For example, the code generated by Visual Studio 2005 for a Windows Form is kept separate from your business logic (we will discuss this in a later section). This will prevent developers from messing with the code that is used for the UI. At the same time, it will prevent you from losing your changes to the designer-generated code when you change the UI.

The "partial" keyword in VB.NET used to be called "expands" in pre-beta versions of Visual Studio 2005.

Examining Partial Classes
The following code sample shows the class definition of MyClass1. I declared all my properties in this file. To avoid confusion, I named my class file MyClass1.Properties.vb, in order to make it obvious that this file contains a properties definition.
'---MyClass1.Properties.vb
'---one of the classes need not have the Partial keyword
Public Class MyClass1
Private pX As Integer
Private py As Integer
Property x() As Integer
Get
Return pX
End Get
Set(ByVal value As Integer)
pX = value
End Set
End Property
Property y() As Integer
Get
Return py
End Get
Set(ByVal value As Integer)
py = value
End Set
End Property
End Class
In another file, named MyClass1.Methods.vb, I provide the methods implementation of MyClass1. I used the Partial keyword to indicate that this definition should be combined with the original MyClass1 definition.
'---MyClass1.Methods.vb
'---must have the Partial keyword
Partial Public Class MyClass1
Private py As Integer

Public Sub method1()
' implementation here
End Sub

Public Sub method3(ByVal x As Integer, ByVal y As Integer)
' implementation here
End Sub

Public Sub method2()
' implementation here
End Sub
End Class
In reality, you can mix and match properties and method definitions in any of the files, but for clarity it is a good idea to group properties definitions in one file and methods definitions in another. The usual rules of OO apply: If there is a method1 in both files, then both method1s must have unique signatures.

The syntax of partial classes in VB.NET and C# differs slightly. The following shows the implementation of partial classes in C#:
// In C#, the partial keyword must
// appear in all class definitions
public partial class MyClass1
{
public MyClass1()
{
//implementation here
}
}

public partial class MyClass1
{
//implementation here
}
Besides the order in which the "partial" keyword is placed, the most significant difference is the strict enforcement of the use of the "partial" keyword in all partial classes in C#. It is mandatory, whereas in VB.NET, not all of the partial classes have to have the "partial" keyword. This has caused a significant amount of newsgroup discussion about the rationale for the difference. My advice is that you should always prefix partial classes with the "partial" keyword. At least this will give you a visual clue that part of the implementation of the class lies somewhere else, and it is definitely useful when it comes to debugging.

While partial classes allow you to split the definition of a class into multiple files, you cannot mix languages. That is, all partial classes must be written in the same language. Besides using the "partial" keyword for classes, you can also use it for structures and interfaces.

If your class implements multiple interfaces, it is a good idea to use partial classes to contain the implementation for each interface.

Hide-protecting code is one of the best uses of partial classes; you can prevent mishaps and provide useful code-layer abstraction at the same time. In Visual Studio 2005, Microsoft uses partial classes to hide designer-generated code. For example, in Visual Studio .NET 2003, the designer-generated code for a Windows form is encapsulated within the region "Windows Form Designer generated code"Very often, developers will accidentally modify the code within this region and cause the form to display incorrectly.


In Visual Studio 2005 however, the designer-generated code is no longer visible in the Code View window (see Figure 2). Instead, it is hidden within Solution Explorer.

To see the designer-generated code, go to Solution Explorer and click on the Show All Files button (see Figure 3). Under the name of the Windows form, you will see a file post fixed with the "Designer.vb" name. Double-clicking on Form1.Designer.vb will reveal the designer-generated code:
Partial Public Class Form1
Inherits System.Windows.Forms.Form

_
Public Sub New()
MyBase.New()

'This call is required by the
' Windows Form Designer.
InitializeComponent()
...
Notice that the Form1.Designer.vb file appears under the Form1.vb file in Solution Explorer. This is a good way to represent the relationship between the two files. So what does Visual Studio do to represent this relationship? The answer lies in the .vbproj or .csproj (for C# projects) file. Open the file in Notepad and use Ctrl + F to locate the element:
...


Form


Form1.vb
Form

...
As you can see, the element indicates that Form1.Designer.vb is dependent on Form1.vb. So how is this information useful to us?

Recall that earlier in this article I mentioned two partial classes, MyClass1.methods.vb and MyClass1.properties.vb. Assume that these two classes serve as a template and contain general-purpose functions (and you generally would not make changes to these two classes). You may add a third partial class to add business-specific functions. And so, it would be useful to hide the first two partial classes in Solution Explorer by modifying the .vbproj/.csproj file:


MyClass1


MyClass1.vb
MyClass1


MyClass1.vb
MyClass1

When the project is loaded in Visual Studio 2005, you should see the two partial classes hidden

Unfortunately, at this moment you need to manually modify the project file in order to hide partial classes. Hopefully in the next beta Microsoft will build this function into Visual Studio. Or someone else will write a plugin for that.

In this article, you have seen how to split the definitions of a class into multiple classes using the "partial" keyword. The greatest use of partial classes is undoubtedly the separation of UI and business logic. I am interested to know how else you may be using partial classes.

Friday, September 02, 2005

Executing ASPX pages without a web server : Kaushal Patel

For the last couple of days, I?ve been writing about creating a standalone ASPX execution environment?a Windows Forms application that executes an ASP.NET page and displays the results in a Web Browser control.

Because of the way the ASP libraries are written, this effectively requires either a couple of communicating but distinct assemblies or a strongly-named assembly in the Global Assembly Cache. In my project, I wrote two distinct assemblies, which worked. But I wondered if I could overcome this requirement, with the hope that I would learn a thing or two in the process. It took some code spelunking (and a venture beyond what is documented), but I succeeded on both fronts.

The article that got me started on this project was Ted Neward?s "Hosting ASP.NET: Running an All-Managed HTTP Server," which I can?t recommend highly enough. Neward opted for the two assembly approach (or more exactly, the same assembly copied into two different directories). My code still retains a class from his example. But while he uses an ASP.NET function to spin up the app domain that the ASPX page runs in, I create mine from scratch.

Here?s a little console app I created:

using System;
using System.Web;
using System.Web.Hosting;
using System.IO;
using System.Runtime.Remoting;
using System.Globalization;
namespace AspHostTest
{
public class MyExeHost : MarshalByRefObject
{
public void ProcessRequest(String page)
{
HttpWorkerRequest hwr =
new SimpleWorkerRequest(page, null, Console.Out);
HttpRuntime.ProcessRequest(hwr);
}
}
class MyAspHost
{
public static object CreateApplicationHost(Type hostType, string virtualDir, string physicalDir)
{
if (!(physicalDir.EndsWith("\\")))
physicalDir = physicalDir + "\\";
string aspDir = HttpRuntime.AspInstallDirectory;
string domainId = DateTime.Now.ToString(DateTimeFormatInfo.InvariantInfo).GetHashCode().ToString("x");
string appName = (virtualDir + physicalDir).GetHashCode().ToString("x");
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationName = appName;
setup.ConfigurationFile = "web.config"; // not necessary execept for debugging
AppDomain ad = AppDomain.CreateDomain(domainId, null, setup);
ad.SetData(".appDomain", "*");
ad.SetData(".appPath", physicalDir);
ad.SetData(".appVPath", virtualDir);
ad.SetData(".domainId", domainId);
ad.SetData(".hostingVirtualPath", virtualDir);
ad.SetData(".hostingInstallDir", aspDir);
ObjectHandle oh = ad.CreateInstance(hostType.Module.Assembly.FullName, hostType.FullName);
return oh.Unwrap();
}

static void Main(string[] args)
{
MyExeHost myHost = (MyExeHost)CreateApplicationHost(typeof(MyExeHost),"/",Directory.GetCurrentDirectory());
myHost.ProcessRequest("app.aspx");
}
}
}

To compile it, open a Visual Studio .NET command prompt (or any other command prompt session with the C# compiler in the path) and run this command:

csc /t:exe /r:System.Web.dll AppHostTest.cs
Put the exe file in a directory with an ASPX file named app.aspx. Here?s the simple file I?ve used in my tests:

Hello, world.


Today is
<%= DateTime.Now %>.



When you run AppHostTest.exe, you?ll see the raw html that the executed ASPX file creates.

In addition to running this program, you can use VS.NET to debug right into the ASP.NET page. For this to work, you?ll have to instruct the ASP.NET classes to compile your code with debug symbols. You can do this by creating a file called web.config in the same directory. All this file needs to contain is the following XML:







To load the debugger, run this command from the same directory:

devenv /debugexe AspHostText.exe
Load the ASPX file with the Open/File? menu choice, set a breakpoint on a line of code, press F5, and you should see the debugger stop at that line.

Okay. That was fun, but what exactly is going on in the code?

What we?ve done is to create two classes. MyAspHost includes the Main method that runs the show and a static method I?ve called CreateApplicationHost. This latter method serves the same purpose (and takes the same parameters) as a static method of the same name in the System.Web.Hosting.ApplicationHost class. The ASP.NET method does more, and calls a lot of protected functions in the process.

My method does the minimum that is required to get a simple ASPX page to execute, which is to create an app domain, create an object in the app domain, and return a reference to this object to the calling program (in the default app domain). That's essentially what the ASP.NET classes do, but I've left out what isn't absolutely necessary. (The domain ID and application name could be given simpler names, but I chose to use the same algorithm that ApplicationHost.CreateApplicationHost uses.)

The other class in the file is the one that gets instantiated in the new app domain. All it does is create a System.Web.Hosting.SimpleWorkerRequest specifying the page to run and the output System.IO.TextWriter, then hand this request to a static method in the System.Web.HttpRuntime class, which does all the rest.

Next week I?ll write about the documented way to do this same thing, but I should mention the difference between this code and the Kosher code. The salient difference (apart from all the other things I left out) is that the ASP.NET code sets up a PrivateBinPath for the new app domain so it looks for the assembly it creates in a bin directory below the virtual root is uses. This explains the need for the second assembly?ASP.NET forces the Fusion assembly resolver to look for this assembly in a separate place. That?s what allows my code to be so simple; I allow Fusion to look for the new assemblies in the same directory as the executable.

Executing ASPX pages without a web server

For the last couple of days, I?ve been writing about creating a standalone ASPX execution environment?a Windows Forms application that executes an ASP.NET page and displays the results in a Web Browser control.

Because of the way the ASP libraries are written, this effectively requires either a couple of communicating but distinct assemblies or a strongly-named assembly in the Global Assembly Cache. In my project, I wrote two distinct assemblies, which worked. But I wondered if I could overcome this requirement, with the hope that I would learn a thing or two in the process. It took some code spelunking (and a venture beyond what is documented), but I succeeded on both fronts.

The article that got me started on this project was Ted Neward?s "Hosting ASP.NET: Running an All-Managed HTTP Server," which I can?t recommend highly enough. Neward opted for the two assembly approach (or more exactly, the same assembly copied into two different directories). My code still retains a class from his example. But while he uses an ASP.NET function to spin up the app domain that the ASPX page runs in, I create mine from scratch.

Here?s a little console app I created:

using System;
using System.Web;
using System.Web.Hosting;
using System.IO;
using System.Runtime.Remoting;
using System.Globalization;
namespace AspHostTest
{
public class MyExeHost : MarshalByRefObject
{
public void ProcessRequest(String page)
{
HttpWorkerRequest hwr =
new SimpleWorkerRequest(page, null, Console.Out);
HttpRuntime.ProcessRequest(hwr);
}
}
class MyAspHost
{
public static object CreateApplicationHost(Type hostType, string virtualDir, string physicalDir)
{
if (!(physicalDir.EndsWith("\\")))
physicalDir = physicalDir + "\\";
string aspDir = HttpRuntime.AspInstallDirectory;
string domainId = DateTime.Now.ToString(DateTimeFormatInfo.InvariantInfo).GetHashCode().ToString("x");
string appName = (virtualDir + physicalDir).GetHashCode().ToString("x");
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationName = appName;
setup.ConfigurationFile = "web.config"; // not necessary execept for debugging
AppDomain ad = AppDomain.CreateDomain(domainId, null, setup);
ad.SetData(".appDomain", "*");
ad.SetData(".appPath", physicalDir);
ad.SetData(".appVPath", virtualDir);
ad.SetData(".domainId", domainId);
ad.SetData(".hostingVirtualPath", virtualDir);
ad.SetData(".hostingInstallDir", aspDir);
ObjectHandle oh = ad.CreateInstance(hostType.Module.Assembly.FullName, hostType.FullName);
return oh.Unwrap();
}

static void Main(string[] args)
{
MyExeHost myHost = (MyExeHost)CreateApplicationHost(typeof(MyExeHost),"/",Directory.GetCurrentDirectory());
myHost.ProcessRequest("app.aspx");
}
}
}

To compile it, open a Visual Studio .NET command prompt (or any other command prompt session with the C# compiler in the path) and run this command:

csc /t:exe /r:System.Web.dll AppHostTest.cs
Put the exe file in a directory with an ASPX file named app.aspx. Here?s the simple file I?ve used in my tests:

Hello, world.


Today is
<%= DateTime.Now %>.



When you run AppHostTest.exe, you?ll see the raw html that the executed ASPX file creates.

In addition to running this program, you can use VS.NET to debug right into the ASP.NET page. For this to work, you?ll have to instruct the ASP.NET classes to compile your code with debug symbols. You can do this by creating a file called web.config in the same directory. All this file needs to contain is the following XML:







To load the debugger, run this command from the same directory:

devenv /debugexe AspHostText.exe
Load the ASPX file with the Open/File? menu choice, set a breakpoint on a line of code, press F5, and you should see the debugger stop at that line.

Okay. That was fun, but what exactly is going on in the code?

What we?ve done is to create two classes. MyAspHost includes the Main method that runs the show and a static method I?ve called CreateApplicationHost. This latter method serves the same purpose (and takes the same parameters) as a static method of the same name in the System.Web.Hosting.ApplicationHost class. The ASP.NET method does more, and calls a lot of protected functions in the process.

My method does the minimum that is required to get a simple ASPX page to execute, which is to create an app domain, create an object in the app domain, and return a reference to this object to the calling program (in the default app domain). That's essentially what the ASP.NET classes do, but I've left out what isn't absolutely necessary. (The domain ID and application name could be given simpler names, but I chose to use the same algorithm that ApplicationHost.CreateApplicationHost uses.)

The other class in the file is the one that gets instantiated in the new app domain. All it does is create a System.Web.Hosting.SimpleWorkerRequest specifying the page to run and the output System.IO.TextWriter, then hand this request to a static method in the System.Web.HttpRuntime class, which does all the rest.

Next week I?ll write about the documented way to do this same thing, but I should mention the difference between this code and the Kosher code. The salient difference (apart from all the other things I left out) is that the ASP.NET code sets up a PrivateBinPath for the new app domain so it looks for the assembly it creates in a bin directory below the virtual root is uses. This explains the need for the second assembly?ASP.NET forces the Fusion assembly resolver to look for this assembly in a separate place. That?s what allows my code to be so simple; I allow Fusion to look for the new assemblies in the same directory as the executable.