Sunday, June 20, 2010
Sunday, September 02, 2007
Reflection on Generic, Part 3 - Instantiate Generic Type
In this post, we will look at how to use reflection to instantiate a generic type.
First, let start with an example of how to do it in the usual way without reflection.
static void Main(string[] args)The above code will print out
{
List<string> list = InstatiateList();
list.ForEach(delegate(string s) { Console.WriteLine(s); });
Console.ReadLine();
}
private static List<string> InstatiateList()
{
List<string> listOfString = new List<string>();
listOfString.Add("AAA");
listOfString.Add("BBB");
return listOfString;
}
AAA
BBB
Now, lets do it the reflection way.
static void Main(string[] args)
{
List<string> list = InstatiateListReflectionWay();
list.ForEach(delegate(string s) { Console.WriteLine(s); });
Console.ReadLine();
}
private static List<string> InstatiateListReflectionWay()
{
// Get the metadata for List_Of_T
Type t = typeof(List<>);
// Make a type definition for List_Of_String
Type[] typeArg = new Type[1] { typeof(string) };
Type listOfStringDef = t.MakeGenericType(typeArg);
// Get the method metadata for Add() method.
MethodInfo mi = listOfStringDef.GetMethod("Add");
// Create an instance of List_Of_String.
object listOfString = Activator.CreateInstance(listOfStringDef);
// Add two element to the list.
mi.Invoke(listOfString, new object[] { "CCC" });
mi.Invoke(listOfString, new object[] { "DDD" });
return (List<string>)listOfString;
}
The above code will print out:
CCC
DDD
Even when you use reflection, the runtime still give you strongly type checking protection against your code. To prove this, insert the following code before the return statement in InstatiateListReflectionWay().
mi.Invoke(listOfString, new object[] { 123 });
This time, when you run the code again, you will see an exception thrown.
Exception thrown when insert a number into list_of_string. Click to view in full size.
Reflection on Generic, Part 2 - Reflecting Type Parameter
In the previous post, you have know how to retrieve type metadata for a generic type. In this post, let's walk through how to retrieve metadata for the type parameter. Let's use the following code as example:
public interface IPrint
{
string Print();
}
public class PrintingDevice<T> where T: class, IPrint, new()
{
public T Device;
}
public class ValueGenericType<T> where T : struct
{
public T Value;
}
....
private static void DumpType(Type t)
{
Console.WriteLine("Is Generic Type : {0}", t.IsGenericType);
Console.WriteLine("Type Name : {0}", t.FullName);
Type[] genericArguments = t.GetGenericArguments();
Console.WriteLine("Number of type parameter : {0}", genericArguments.Length);
foreach (Type typeArg in genericArguments)
{
// Check whether the current type represent a Generic Parameter.
Console.WriteLine("Is Generic Parameter : {0}", typeArg.IsGenericParameter);
// Get the constraint specified for type parameter
GenericParameterAttributes attr = typeArg.GenericParameterAttributes;
if ((attr & GenericParameterAttributes.DefaultConstructorConstraint) !=
GenericParameterAttributes.None)
{
Console.WriteLine("Default constructor constraint specified.");
}
if ((attr & GenericParameterAttributes.ReferenceTypeConstraint) !=
GenericParameterAttributes.None)
{
Console.WriteLine("Reference type constraint specified.");
}
if ((attr & GenericParameterAttributes.NotNullableValueTypeConstraint) !=
GenericParameterAttributes.None)
{
Console.WriteLine("Value type constraint specified.");
}
Type[] typeConstraints = typeArg.GetGenericParameterConstraints();
if (typeConstraints.Length > 0)
{
foreach (Type typeConstraint in typeConstraints)
{
Console.WriteLine("Type Constraint : {0}", typeConstraint.FullName);
}
}
else
{
Console.WriteLine("No type constraint specified.");
}
}
}
Run the following code with PrintingDevice,
Type t = typeof(PrintingDevice<>);
DumpType(t);
and the outcome will be :
Is Generic Type : True
Type Name : GenericConstraint.PrintingDevice`1
Number of type parameter : 1
Is Generic Parameter : True
Default constructor constraint specified.
Reference type constraint specified.
Type Constraint : GenericConstraint.IPrint
Run the code again with ValueGenericType,
Type t = typeof(ValueGenericType<>);
DumpType(t);
and the outcome will be :
Is Generic Type : True
Type Name : GenericConstraint.ValueGenericType`1
Number of type parameter : 1
Is Generic Parameter : True
Default constructor constraint specified.
Value type constraint specified.
Type Constraint : System.ValueType
Type.GetGenericArguments() will return an array of type parameters specified for the generic type.
Type.IsGenericParameter will return true if the current type represent a type parameter. If the type represent a type parameter, then the type will have no name.
Type.GenericParameterAttributes will return the constraints specified for that type parameter.
Type.GetGenericParameterConstraints() will return an array of type that are specified as the constraint for the type parameter.
Reflection on Generic, Part 1
You can use reflection against generic type to get metadata information about a generic type as well as instantiate a generic type with type argument. In this post, I will walk you through how to retrieve metadata about a generic type.
To check whether a type is a generic type, you use the Type.IsGenericType property.
Let start with a simple example:
Type s = typeof(string);
// This will print False.
Console.WriteLine(s.IsGenericType);
// This will print System.String
Console.WriteLine(s.FullName);
Since System.String is not a generic type, it will print False. Now let's use an example with generic type:
Type t = typeof(List<>);
// This will print True.
Console.WriteLine(t.IsGenericType);
// This will print System.Collections.Generic.List`1.
Console.WriteLine(t.FullName);
Type d = typeof(Dictionary<,>);
// This will print True.
Console.WriteLine(d.IsGenericType);
// This will print System.Collections.Generic.Dictionary`2.
Console.WriteLine(d.FullName);
In the above example, both will print True. Note that to retrieve type metadata for a generic type, you need to use the <> after the generic type name to denote the number of type parameters specified for that generic type. The number of type parameters are part of the type signature. It is perfectly legal to declare the following:
class C1<Y> { ... }
class C1<Y,T> { ... }
Going back to the example, since List only has one type paratemer, I just specify <> to indicate I want to the List generic class with one type parameter. For Dictionary class take take two type parameter, I specify <,> to indicate I want the Dictionary generic class with two type parameter.
When print out the full name of the class, notice that there is a number at the end of the class name. The number is called Arity which indicate the number of type parameter that the generic type have.
Thursday, August 30, 2007
NET: Checking what is the type argument
The following code sample show how you can check what is the type of the type argument passed to instantiate the generic type.
public class TypeDisplayer<T>
{
public string GetTypeArgument() { return typeof(T).FullName; }
}
static void ShowGenericTypeArgument()
{
//This will print System.Int32.
TypeDisplayer<int> i = new TypeDisplayer<int>();
Console.WriteLine(i.GetTypeArgument());
//This will print System.String.
TypeDisplayer<string> s = new TypeDisplayer<string>();
Console.WriteLine(s.GetTypeArgument());
}
NET: Generic Constraint Type - Default Constructor Constraint Type
Default Constructor constraint allow you to specify that the type parameter must have a default/parameterless constructor. This is useful if you want to create a new object instance of the type argument.
public class DefaultConstructorGenericType<T> where T : new()
{
public T Value;
public DefaultConstructorGenericType()
{
Value = new T();
}
}
public class ClassWithDefaultCon
{
public ClassWithDefaultCon() {}
}
public class ClassB
{
public int a;
public ClassB(int v) { a = v;}
}
static void InstantiateDefault()
{
// This code will compile fine.
DefaultConstructorGenericType<ClassWithDefaultCon> vt =
new DefaultConstructorGenericType<ClassWithDefaultCon>();
// This code will give compile error
// because ClassB does not have default constructor
DefaultConstructorGenericType<ClassB> vt =
new DefaultConstructorGenericType<ClassB>();
}
In the above sample, DefaultConstructorGenericType can only accept a type argument that has a default constructor. where keyword is used to specify a generic constraint in C#. In the above code sample, I specify that type parameter T has to have default constructor (indicate by where T : new()).
Wednesday, August 29, 2007
NET: Generic Constraint Type - Inheritance Constraint Type
Inheritance type constraint allow you to specify that the type parameter must be derive from certain base class or interface. It is useful if you want to assume the type argument to be of certain type so that you can call method on the instance of the type argument. Visual Studio will give you full intellisense support.
public interface IPrint
{
void Print();
}
public class Printer : IPrint
{
public void Print()
{
// Do something
}
}
public class PhotoCopier
{
public void PhotoCopy()
{
// Do something.
}
}
public class DeviceWrapper<T> where T : IPrint
{
public T Device;
}
static void InstantiateDevice()
{
// This code will compile fine.
DeviceWrapper<Printer> vt =
new DeviceWrapper<Printer>();
// This code will give compile error
// because PhotoCopier is not derive from IPrint.
DeviceWrapper<PhotoCopier> vt2 =
new DeviceWrapper<PhotoCopier>();
}
In the above sample, DeviceWrapper can only accept a type argument that is derive from IPrint.
where keyword is used to specify a generic constraint in C#. In the above code sample, I specify that
type parameter T has to be derive from IPrint (indicate by where T : IPrint).
Visual Studio Intellisense support.
NET: Generic Constraint Type - Reference Constraint Type
Reference type constraint allow you to specify that the type parameter must be of reference type.
class GenericReferenceType<T> where T : class
{
public T Value;
}
static void InstantiateRefType()
{
// This code will compile fine.
GenericReferenceType<System.Text.StringBuilder> vt =
new GenericReferenceType<StringBuilder>();
// This code will give compile error
//because Point is not reference type.
GenericReferenceType<System.Drawing.Point> vt2 =
new GenericReferenceType<System.Drawing.Point>();
}
In the above sample, GenericReferenceType can only accept a reference type as its type parameter.
where keyword is used to specify a generic constraint in C#. In the above code sample, I specify that
type parameter T has to be of reference type (indicate by where T : class).
NET: Introduction to Generic Constraint Type
Generic constraint allow you to specify constraint/rule that limit what .net type can be used as type argument when you instantiate a generic type.
In this post, I will show a short code sample of how to use the various generic constraint.
For more explaination about Generic Constraint, visit msdn
How to specify constraint value type
Value type constraint allow you to specify that the type parameter must be of value type.
class GenericValueType<T> where T : struct
{
public T Value;
}
static void InstantiateValueType()
{
// This code will compile fine.
GenericValueType<System.Drawing.Point> vt =
new GenericValueType<System.Drawing.Point>();
// This code will give compile error
//because StringBuilder is not value type.
GenericValueType<System.Text.StringBuilder> vt2 =
new GenericValueType<StringBuilder>();
}
where keyword is used to specify a generic constraint in C#. In the above code sample, I specify that type parameter T has to be of value type (indicate by where T : struct).
Tuesday, February 27, 2007
NET : Ignore field for XML Serialization
You can ignore certain public field from being serialize if the value for that field
is not specified.
XmlSerializer recognize a specific pattern during serialization to ignore
or include a field into the serialization.
Here are the steps :
1) You create a public field (EG : public int Age).
2) Create a boolean field using the convention PropertyNameSpecified (EG : public boolean AgeSpecified).
3) Apply XmlIgnoreAttribute attribute to the boolean property.
Refer to the following code.
public class Customer
{
public string Name;
public int Age;
[XmlIgnore()]
public bool AgeSpecified;
}
Here is the code to serialize the Customer object. Notice I set the AgeSpecified to false to tell the XmlSerializer not to serialize the Age field.
static void SerializeData()
{
Customer c = new Customer();
c.Name = "Bob";
c.Age = 21;
c.AgeSpecified = false;
XmlSerializer serializer = new XmlSerializer(typeof(Customer));
FileStream fs = new FileStream("simple.xml", FileMode.Create);
// Serialize the object
serializer.Serialize(fs, c);
fs.Close();
}
If you open simple.xml in notepad, you will see that there is no Age field.

Run the following code to deserialize the object from the file.
static void DeserializeData()
{
Customer c = null;
XmlSerializer serializer = new XmlSerializer(typeof(Customer));
FileStream fs = new FileStream("simple.xml", FileMode.Open);
c = (Customer)serializer.Deserialize(fs);
fs.Close();
Console.WriteLine("Age : " + c.Age);
Console.WriteLine("Specified : " + c.AgeSpecified);
}

Now run the serialize and deserialize code again, but this time set the AgeSpecified to true, and below is
the output :


Labels: DotNet
Monday, February 05, 2007
Exception : {Throw} vs {Throw ex}
I have seen two way how people typically throw exception:
Example 1:
try
{
//...
}
catch(Exception ex)
{
throw;
}
Example 2:
try
{
//...
}
catch(Exception ex)
{
throw ex;
}
While both accomplish the objective, which is to throw the exception back to the
caller for further action, it has substle difference.
In the first example, it is considered you are re-throwing the existing exception.
The exception contain the full stack frame from where the exception is orginated
all the way up to the caller stack frame.
Run the sample code below, and you shall see the stack trace as below. Notice, at each stack frame, the stack trace contain the stack frame of where the exception is orginated all the way up to the caller stack frame.

In the second example, it is considered you are throwing a new exception.
The exception only contain stack frame of the caller and the frame which throw
the exception. Run the sample code again, but this time change the throw to throw ex. This time, you will notice at each stack frame, the stack trace only contain the stack frame of the callee and the caller. So, you lose information of where the exception is originated. This can make locating the source of error very difficult.

Sample Code
class Class1
{
[STAThread]
static void Main(string[] args)
{
try
{
Console.WriteLine(f1());
}
catch(Exception ex)
{
Console.WriteLine("---Exception in Main()---");
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace.ToString());
}
Console.ReadLine();
}
static int f1()
{
try
{
return f2();
}
catch(Exception ex)
{
Console.WriteLine("---Exception in f1()---");
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace.ToString());
throw;
}
}
static int f2()
{
try
{
return f3();
}
catch(Exception ex)
{
Console.WriteLine("---Exception in f2()---");
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace.ToString());
throw;
}
}
static int f3()
{
int a = 0;
int b = 1;
try
{
return b /a;
}
catch(Exception ex)
{
Console.WriteLine("---Exception in f3()---");
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace.ToString());
throw;
}
}
}
Labels: DotNet
Tuesday, February 07, 2006
.NET20 : DPAPI Wrapper
In .NET 1.1, if you want to use DPAPI to protect your secret data, you need to use P/Invoke and write your own wrapper class to call the DPAPI function.
However, In .NET 2.0, the DPAPI wrapper class has been built into the framework itself.The class is ProtectedData in System.Security.Cryptography namespace.
Labels: DotNet
Sunday, November 27, 2005
Using DebuggerStepThroughAttribute
You can use System.Diagnostics.DebuggerStepThroughAttribute to prevent the Visual Studio debugger from stopping at the method/property call when you step through you code.
For example, you have a program like this :
1using System;
2using System.Diagnostics;
3
4namespace DebuggerStepThrough_Demo
5{
6 public class Employee
7 {
8 public Employee()
9 {
10 _name = "";
11 _salary = 0;
12 }
13
14 public Employee(string name, double salary)
15 {
16 _name = name;
17 _salary = salary;
18 }
19
20 private double _salary;
21 public double Salary
22 {
23 set { _salary = value; }
24 get { return _salary; }
25 }
26
27 private string _name;
28 public string Name
29 {
30 set { _name = value; }
31 get { return _name; }
32 }
33
34 public double IncreaseSalary(double amount)
35 {
36 Salary += amount;
37 return Salary;
38 }
39 }
40
41 class Class1
42 {
43 [STAThread]
44 static void Main(string[] args)
45 {
46 Employee emp = new Employee("My Name", 1000);
47
48 emp.IncreaseSalary(emp.Salary * 0.5);
49
50 }
51 }
52}
53
When you put a breakpoint at the line emp.IncreaseSalary(emp.Salary * 0.5);, and you step through the code in the debugger, the debugger will step into the get method of Salary property before the IncreaseSalary method. You can stop this by using the DebuggerStepThroughAttribute attribute.
1 public double Salary
2 {
3 set { _salary = value; }
4
5 [DebuggerStepThrough()]
6 get { return _salary; }
7 }
8
Now, when you step through the code again in debugger, the debugger will step into IncreaseSalary right away.
This is useful if your property getter and setter does not perform complex situation and you don't want
to step into those code during debugging.
Labels: DotNet
Sunday, April 24, 2005
JIT optimization on for loop
Brad Abram blog explaining the performance of using cached and non-cached variable in for loop and array bound checking.
Knowing the reason will break you out of the old school of thaught on performance optimization.
Labels: DotNet
Thursday, February 10, 2005
Detect Windows Idle time
Here is a sample code of how you can detect idle time in Windows. The definition of idle time here refer to the time when there is no user interaction with Windows such as no keyboard and mouse input.
Detecting idle time is used in application like MSN Messenger to change the status to "Away" after the user does not interact with the Windows for a predefine time.
The enabler for this feature is the GetLastInputInfo() Win32 API and the LASTINPUTINFO Win32 structure.
1. Create a C# Winform project in Visual Studio .NET.
2. Drop a Timer, Label and Button onto the form.
3. Set the Timer Interval property to 1000(1 second).
4. Create a Click event handler for the button.
5. Create a Tick event handler for the timer.
6. Use the following code to complete the Winform code.
7. Then you can build the project and run the app.
8. When the application is running, click the button to enable to timer.
9. Stay your hand away from your keyboard and mouse.
10. You can see the lable is showing the number of seconds that the Windows has been idle.
11. The moment you move your mouse or press any key, the number is reset.
Disclaimer:
The sample code only serve as a mean to illustrate the concept and implementation. It has not been checked for minor bugs, quality and robustness.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace GetLastInput_Demo
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
[DllImport("user32.dll")]
static extern bool GetLastInputInfo(out LASTINPUTINFO plii);
[StructLayout( LayoutKind.Sequential )]
struct LASTINPUTINFO
{
public static readonly int SizeOf =
Marshal.SizeOf(typeof(LASTINPUTINFO));
[MarshalAs(UnmanagedType.U4)]
public int cbSize;
[MarshalAs(UnmanagedType.U4)]
public int dwTime;
}
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Timer timer1;
private System.ComponentModel.IContainer components;
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
private void InitializeComponent()
{
// Code is omitted here.
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void button1_Click(object sender, System.EventArgs e)
{
timer1.Enabled = !timer1.Enabled;
}
private void timer1_Tick(object sender, System.EventArgs e)
{
int idleTime = 0;
LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
lastInputInfo.cbSize = Marshal.SizeOf( lastInputInfo );
lastInputInfo.dwTime = 0;
int envTicks = Environment.TickCount;
if( GetLastInputInfo( out lastInputInfo ) )
{
int lastInputTick = lastInputInfo.dwTime;
idleTime = envTicks - lastInputTick;
}
int a;
if(idleTime > 0)
a = idleTime / 1000;
else
a = idleTime;
label1.Text = a.ToString();
}
}
}
Labels: DotNet
Tuesday, November 02, 2004
Writing on .NET strong name assembly.
One of my friend posted some articles on CodeProject in regards to .NET strong name assembly.
Here are the links :
Building Security Awareness in .NET Assemblies : Part 1 - Learn to break a .NET Assembly
Building Security Awareness in .NET Assemblies : Part 2 - Learn to protect your .NET assemblies from being tampered
Building Security Awareness in .NET Assemblies : Part 3 - Learn to break Strong Name .NET Assemblies
Labels: DotNet
Thursday, October 28, 2004
Deploying Assembly/DLL in different folder for ASP.NET
Some time earlier, I blog about how to deploy assembly/DLL in subfolders of the main app folder for Winform application :
http://dataerror.blogspot.com/2004/10/deploy-net-assembly-in-different.html
Scott Hanselman posted the technique how to do the same for ASP.NET application.
http://www.hanselman.com/blog/PermaLink.aspx?guid=4d0ef4fb-f8ae-4355-a658-3c0432c98dbe
Labels: DotNet
Monday, October 04, 2004
Deploy .Net Assembly in different folder
By default, the CLR will look for the assembly files(dll) in the same directory as the application(exe). If it cannot find the dll, a FileNotFound exception will be throw.
This might not be desirable if your application has a large number of dll that it reference. For example, if your application support plug-ins, you might want all the plug-ins to be put into another directory call 'plugin'.
There is 2 ways to deploy the dll into a different directory. However, this folder is relative to your application directory. You cannot deploy the dll outside your application directory.
Method 1
You can deploy the dll in a sub directory that has the same name as the dll.
For example:
You have 2 files, myapp.exe and mydll.dll. You deploy myapp.exe in your application folder, and deploy mydll.dll in a sub directory named 'mydll'.
It should look something like this :
\program files\MyGreatesApp\myapp.exe
\program files\MyGreatesApp\mydll\mydll.dll
Method 2
You can use a application configuration file to specify the private path the CLR
should search for to locate the dll.
For example, you place you exe and dll in the following directory :
\program files\MyGreatesApp\myapp.exe
\program files\MyGreatesApp\plugin\myplugin.dll
This is how your application configuration file should look like :
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="plugin"/>
</assemblyBinding>
</runtime>
</configuration>
If you have multiple directory, you can specify the all the directories using a semicolon delimited string. But take note that it cannot have any space in between the semicolon.
Example :
<probing privatePath="plugin;library"/>
Labels: DotNet
Tuesday, August 24, 2004
Why You Would Use App Domain?
There are 3 reasons:
1) To dynamically load and unload assembly. You can load an assembly, but you can't unload it because the CLR cannot keep track of all dependency of assembly. One workaround is to load these assemblies into a different app domain and unload the app domain once you are done.
2) For security reason. You can apply CAS to app domain to secure it from doing dangerous thing.
3) Different configuration setting. You can have different setting for each app domain that make it behave differently.
Labels: DotNet
Tuesday, August 03, 2004
Draw with Inverse Color
After some research and testing, finally has figure out how to draw a rectangle using a color that is the inverse of its drawing surface. The code make use of PInvoke to GDI32 functions.
Here is the sample code :
public sealed class GDI32
{
public const int R2_NOT = 6;
public const int NULL_BRUSH = 5;
public const int HOLLOW_BRUSH = NULL_BRUSH;
[DllImport("gdi32.dll", EntryPoint="SetROP2")]
public static extern int SetROP2(IntPtr hDc, int fnDrawMode);
[DllImport("gdi32.dll", EntryPoint="SelectObject")]
public static extern IntPtr SelectObject(IntPtr hdc,IntPtr bmp);
[DllImport("gdi32.dll", EntryPoint="Rectangle")]
public static extern bool Rectangle(IntPtr hdc,int x, int y, int x2, int y2);
[DllImport("gdi32.dll", EntryPoint="GetStockObject")]
public static extern IntPtr GetStockObject(int fnObject);
}
public sealed class USER32
{
[DllImport("user32.dll",EntryPoint="GetDC")]
public static extern IntPtr GetDC(IntPtr ptr);
}
IntPtr p = USER32.GetDC(this.Handle); // System.Windows.Forms.Form.Handle
GDI32.SetROP2(p, GDI32.R2_NOT);
GDI32.SelectObject(p, GDI32.GetStockObject(GDI32.HOLLOW_BRUSH));
GDI32.Rectangle(p, sx, sy, cx, cy);
However, calling the code intensively will cause a performance hit. I use the code in the Winform's MouseMove event to draw the rectangle, and the performance degrades is evident. I have do some work to minimize the PInvoke call but it is still a slow code.
Labels: DotNet, programming