Monday, June 20, 2005

 

Reflection - Calling Methods using Reflection

To call a method of a type that is retrieved from System.Type, you will use the Invoke() method that is contained in MethodInfo.

object Invoke (object ob, object[] args)

ob is the reference to the object on which the method is invoked. For static method, ob should be null.

args specifies any arguments to be passed to the method. If no arguments, args should be null.
Args must contain exactly the same number of elements as there are arguments.

Here's a sub-program that does that:

Type t = typeof(MyClass);
MyClass reflectOb = new MyClass(10, 20);
int val;

Console.WriteLine("Invoking methods in " + t.Name);
Console.WriteLine();
MethodInfo[] mi = t.GetMethods();

// Invoke each method
foreach (MethodInfo m in mi)
{
ParameterInfo[] pi = m.GetParameters();

if (m.Name == "set" && pi[0].ParameterType == typeof(int))
{
object[] args = new object[2];
args[0] = 9;
args[1] = 18;
m.Invoke(reflectOb, args);
}
}

(From C#: The Complete Reference by Schidlt)
 

Reflection - Getting Method Info

Reflection - obtaining information about a type, comes from the way the reflection process works: A Type object questions and it returns (reflects) the information associated with the type, back to you.

It allows one to learn and use the capabilities of types that are known only at runtime.

Obtaining Information about Members

Once a Type object is obtained, the list of all its methods can be retrived by using the GetMethods() method. It has this form:

MethodInfo[] GetMethods()

It returns an array of MethodInfo objects that describe the methods supported by the invoking type.

Here is a program that uses reflection to obtain the methods supported by a class called MyClass.
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace AnalyzeMethods
{
class MyClass
{
int x;
int y;

public MyClass(int i, int j)
{
x = i; y = j;
}

public int sum()
{
return x + y;
}

public bool isBetween(int i)
{
return (x < i && i < y ) ? true : false;
}
public void set(int a, int b)
{
x = a;
y = b;
}

public void set(double a, double b)
{
x = (int)a;
y = (int)b;
}

public void show()
{
Console.WriteLine("x: {0}, y: {1}", x, y);

}
}

class RelectionDemo
{
static void Main(string[] args)
{
Type t = typeof(MyClass);

Console.WriteLine("Analyzing methods in " + t.Name);
Console.WriteLine();
Console.WriteLine("Methods supported: ");

// 1st way to call
//MethodInfo[] mi = t.GetMethods();

// 2nd way to call
// Only method declared by MyClass are obtained.
MethodInfo[] mi = t.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public
| BindingFlags.Instance );

// Dispaly method information
foreach (MethodInfo m in mi)
{
// Display return type and name
Console.Write("\t" + m.ReturnType.Name +
" " + m.Name + "(");

// Display parameters
ParameterInfo[] pi = m.GetParameters();

for (int i = 0; i < pi.Length; i++)
{
Console.Write(pi[i].ParameterType.Name +
" " + pi[i].Name);

if (i + 1 < pi.Length)
Console.Write(", ");
}
Console.WriteLine(")");
}


}
}
}

(Notes obtained from C#: The Complete Reference by Schildt)
 

A simple typeof operator

Just a simple typeof operator:
using System;
using System.IO;

class UseTypeof
{
public static void Main()
{
Type t = typeof(StreamReader);

Console.WriteLine(t.FullName);

if (t.IsClass)
Console.WriteLine("Is a class");
if (t.IsAbstract)
Console.WriteLine("Is abstract");
else
Console.WriteLine("Is concrete.");
}
}

(Taken from C#: The Complete Reference by Schildt)

Result should be:
System.IO.StreamReader
Is a class
Is concrete.

 

Run Type Identification - as operator

If you want to cast an object to another type, but don’t want exceptions to be raised if the cast fails, the as operator is the choice:

expr as type

If the cast succeed: expr will be cast to type type.
If the cast fails: expr will have a null reference.

Here’s an example:
using System;

class A { }
class B : A { }

class CheckCast
{
public static void Main()
{
A a = new A();
B b = new B();

// replace this with
/*
if (a is B)
b = (B)a;
else
b = null;
*/
b = a as B;

if (b == null)
Console.WriteLine("Cast b = (B) a is not allowed.");
else
Console.WriteLine("Cast b = (B) a is allowed.");
}
}

(Taken from the C#: The Complete Reference by Schildt).

The cast will fail, since a is not a B;
 

Runtime Type Identification - is operator

To determine whether an object is of a certain type: we can use the is operator. It will return a boolean result.

expr is type

Returns true if the expression object is of type type or has it derived from type, else it will return false.

This is an example:
using System;

class A { }
class B : A { }

class UseIs
{
public static void Main()
{
A a = new A();
B b = new B();

if (a is A)
Console.WriteLine("a is an A");
if (b is A)
Console.WriteLine("b is an A because it is derived from A");
if (a is B)
Console.WriteLine("Never will be displayed");
else
Console.WriteLine("a is not a B");

if (b is B)
Console.WriteLine("b is a B");
if (a is object)
Console.WriteLine("a is an Object");

}
}

(Taken from C#: The Complete Reference from Herbert Schildt).

The result is
a is an A
b is an A because it is derived from A
a is not a B
b is a B
a is an Object

Monday, May 09, 2005

 

Display Special Environment folders

Display Environment folders
// Display special folders of the computer
using System;

public class GetSpecialFolder
{
public static void Main()
{
Console.WriteLine("Display environment folders of this computer");


Console.WriteLine("Application Data = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
Console.WriteLine("CommonApplicationData = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData));
Console.WriteLine("CommonProgramFiles = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles));
Console.WriteLine("Cookies = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.Cookies));
Console.WriteLine("Desktop = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.Desktop));
Console.WriteLine("DesktopDirectory = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory));
Console.WriteLine("Favorites = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.Favorites));
Console.WriteLine("History = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.History));
Console.WriteLine("InternetCache = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.InternetCache));
Console.WriteLine("LocalApplicationData = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData));
Console.WriteLine("MyComputer = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.MyComputer));
Console.WriteLine("MyMusic = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.MyMusic));
Console.WriteLine("MyPictures = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.MyPictures));
Console.WriteLine("Personal = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.Personal));
Console.WriteLine("ProgramFiles = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles));
Console.WriteLine("Programs = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.Programs));
Console.WriteLine("Recent = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.Recent));
Console.WriteLine("SendTo = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.SendTo));
Console.WriteLine("StartMenu = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.StartMenu));
Console.WriteLine("Startup = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.Startup));
Console.WriteLine("System = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.System));
Console.WriteLine("Templates = \"{0}\"",
Environment.GetFolderPath(Environment.SpecialFolder.Templates));
}
}
The "My Documents" folder is found at Environment.GetFolderPath(Environment.SpecialFolder.Personal) This method will return a string to the path of "My Documents".

Friday, April 29, 2005

 

Mutable Structs

Mutable Structs.

One interesting thing about struct is when you pass them to an ArrayList. Take a look at this code:
using System;
using System.Collections;

public class MutableStruct
{

class Foo
{
public int x;

//public Foo() { x = -1; }

public void Set(int x_)
{ x = x_; }
}

public static void Main()
{
Foo[] fa = new Foo[10];

fa[0] = new Foo();
fa[0].Set(2);


Console.WriteLine(fa[0].x);

// Set an ArrayList of Foo
ArrayList faL = new ArrayList();

faL.Add(new Foo() );
((Foo)faL[0]).Set(2);

Console.WriteLine(((Foo)faL[0]).x);

}
}
The result will be 2 for both as expected. Because Foo is a class, a reference was passed to the ArrayList.

But if you do the following with struct, you get an astonishing answer:
using System;
using System.Collections;

public class MutableStruct
{

struct Foo
{
public int x;

//public Foo() { x = -1; }

public void Set(int x_)
{ x = x_; }
}

public static void Main()
{
Foo[] fa = new Foo[10];

fa[0] = new Foo();
fa[0].Set(2);


Console.WriteLine(fa[0].x);

// Set an ArrayList of Foo
ArrayList faL = new ArrayList();

faL.Add(new Foo() );
((Foo)faL[0]).Set(2);

Console.WriteLine(((Foo)faL[0]).x);

}
}
The value for ((Foo)faL[0]).x was 0 instead of the expected 2. What went “wrong”?

How does a struct differ from a class?

A struct is a value type. What this means is that the object of a struct is placed on the program stack instead of in the heap. This also means that when you copy a struct, or when you assign an object of a struct to another, or when you pass it as an argument to a method, a copy is made. This is in contrast with a class, because with a class, a reference (a pointer) is passed.

However, when you called the Set method of the struct, a secret "ref this" was passed to the method, allowing you to mutate the value of the struct. (This is what mutable struct means). So (this is my interpretation) the actual Set method looks like this:
public void Set(ref this, int x_)
{
this.x = x_;
}
And when you called the Set method, it looks like this fa[0].Set(fa[0], 2). In this case a reference of the struct object (fa[0] is the reference to the first struct object in the Foo array) was passed into the Set method.

So what went “wrong” with the above code is when we called ((Foo)faL[0]).Set(2);, we first invoke the indexer of the ArrayList object, which is nothing but the get/set assessors method. The get method will probably have the following code
return __someObject[indexOfArray];
When this occur, a copy of the Foo object is made. Just like any normal method that returns a value, the value is first copied to a temporary variable and returned.

So faL[0] returns a copy of our Foo object. When we attempt to call the method ((Foo)faL[0]).Set(2). This method will then jam the value 2 into the copied version of our object. Then when the the ((Foo)faL[0]).Set(2); method returns, the copy is destroyed.

The following statment Console.WriteLine(((Foo)faL[0]).x); will yield an value of 0 because the original ((Foo)faL[0]).x hasn’t changed a bit. (A copy of it was returned at both instances:
((Foo)faL[0]).Set(2);
Console.WriteLine(((Foo)faL[0]).x);
For a class Foo a reference was returned instead, allowing us to change its field.

The moral of the story is don’t use mutable structs. Use a class instead, or return a new struct.

Friday, April 22, 2005

 

Trace.Listeners.Clear()

Do not call Trace.Listeners.Clear(), as this will clear of all Debug.Assert() warning messages as well.

Sunday, April 17, 2005

 

Convert integer to binary

To convert any integer to binary (hex or any supported bases). Do teh following:
int number = 32;
Convert.ToString(number, 2);

 

ArrayList.ToArray Method

In order to convert an ArrayList collection to a regular array do the following. (Say you have an ArrayList object called someArrayList and you want to convert it to an array of ints)
int[] intArray = (int[]) someArrayList.ToArray(typeof(int));
I got this help from http://www.lazycoder.com/weblog/arraylisttoarray/

Friday, April 15, 2005

 

Serial Communcation using SerialComm library

Download the source code from http://www.codeproject.com/dotnet/DotNetComPorts.asp

The idea behind Serial port.

In order to use a com port, we instatiate an obect of SerialPort.

The class SerialPort defines several events that we can handle via delegates. This is encapsulated in the WithEvents class. The one-argument constructor of SerialPort takes in an object of WithEvents class.

Prior to using reading or writing to a comm port, the port must be opened via the SerialPortObject.Open(1) method. This method takes in a dummy index (but doesn't really do anything to the index).

The default port configuration for SerialPort resides in the SerialCnfg class. But the best way to configure the port is via the Settings dialog box. This dialog box will automatically serialize the values so that we can use it a second time. If no values are provided, SerialCnfg will use its defaulted value (9600 bps, no hardware handshake, no parity).

Steps to Initiaze the SerialPort

(1) Declare an WithEvent and SerialPort objects
WithEvents serialPortEvents;
SerialPort com1;
(2) Hook up the delegates and instantiate the objects
serialPortEvents = new WithEvents();
serialPortEvents.Error = new StrnFunc(this.OnError);
serialPortEvents.RxChar = new ByteFunc(this.OnRecvI);
serialPortEvents.CtsSig = new BoolFunc(this.OnCts);
serialPortEvents.DsrSig = new BoolFunc(this.OnDsr);
// Get a connection
com1 = new SerialPort(serialPortEvents);
com1.Open(1);
(3) Set up a "Settings" button click event to call the Settings dialog like so
Settings frm = new Settings(com1.ConfigFileName, com1.Cnfg);
frm.ShowDialog();
com1.ConfigFileName is defaulted to "Port1.cfg" in its constructor.

That's it!

Send an array of Byte

(1) Call any one of the overloaded members
public uint Send(byte chr) ;
public uint Send(string s);
public uint Send(byte[] buffer);
The return value is the amount of bytes sent.

That's it!

Receive stuff

Receiving stuff is a bit tricky because there are two ways to receive -- via pooling the com port or via delegate. I’d recommend the delegate method.

This is what you do

(1) Check the OnEvent Receive Mode in the Settings dialog box.

THat's it!

The method delegate you hooked up in the serialPortEvents.RxChar like so:
serialPortEvents.RxChar = new ByteFunc(OnRecvI);
will be called. THe method, like so
void OnRecvI(byte[] byteReceived)
will be called whenever an incoming byte its received.

Friday, March 18, 2005

 

To Create a Text File

Use StreamWriter

Here’s an example

// Screen to file program
using System;
using System.IO;

class LearnStreamWriter
{
public static void Main()
{
StreamWriter fileOut = new StreamWriter("out.txt");
string str;

try {
Console.WriteLine("Enter text ('stop' to quit).");
Console.Write(": ");
while ( (str = Console.ReadLine() ) != "stop" )
{
Console.Write(": ");
fileOut.WriteLine(str);
}
}
catch( Exception e)
{
Console.WriteLine( e.Message);
}
finally
{
fileOut.Close();
}

// Read the file
StreamReader fileIn = new StreamReader("out.txt");

Console.WriteLine("\nYou wrote: ");
Console.WriteLine( fileIn.ReadToEnd() );
}
}

 

StreamReader

StreamReader is StreamWriter’s counterapart.

Here’s a short program to read a text file:

using System;
using System.IO;

class LearnStreamReadWrite
{
public static void Main()
{
string fileName = @"..\..\Class1.cs";

StreamReader fileRead = new StreamReader(fileName);

// Read the content of the file
string aLine = null;
while( (aLine = fileRead.ReadLine()) != null )
{
Console.WriteLine(aLine);
}

}

}

 

StreamWriter

StreamWriter is a character stream wrapper that inherits from TextWriter and is used to wrap a byte IO stream.

StreamWriter(Stream stream)

One way is to use a FileStream object as its constructor such as:


FileStream fout = new FileStream("test.txt", FileMode.Create);
StreamWriter fileOut = new StreamWriter(fout);
Another way is to use the static File members

StreamWriter fileOut = File.CreateText("test.txt"); 
or

StreamWriter fileOut = File.AppendText("test.txt"); 
More Convenient Way
A file can be opened directly using the StreamWriter by one of its constructors:

StreamWriter(string fileName)
StreamWriter(string fileName, bool appendFlag)

If appendFlag is true, the output is appended to the end of an existing file. If the file doesn’t exist, it is created.

StreamWriter.Write()
StreamWriter.WriteLine()
 

FileStream

FileStream enables manipulating of files via byte access.

FileStream is derived from Stream and contains all Stream’s functionality.

To create a byte straem linked to a file, create a FileStream object:

FileStream(string fileName, FileMode mode)

This constructor will depending on the mode specified, access the file with read / write capability

FileMode
FileMode.Append
Output is appended to the end of file

FileMode.Create
Creates a new output file. Any existing file with the same name will be deleted.

FileMode.CreateNew
Creates a new output file - the file must not already exist. (If the file exist, IOException will be thrown)

FileMode.Open
Opens an existing file

FileMode.OpenOrCreate
Opens a file if it exists, or creates the file if it does not already exist.

FileMode.Truncate
Opens a pre-existing file, but reduces its length to zero.

FileStream(string fileName, FileMode mode, FileAccess how)

The mode specifies how the file will be opened. FileAccess determines how the file can be accessed.

FileAccess.Read
Data can be read from the file

FileAccess.ReadWrite
Data can be written to and read from the file

FileAccess.Write
Data can be written to the file

void FileStream.Close()
When one’s done with the file, the Close() method should be called.

Read from a File

int FileStream.ReadByte()
Each time it is called, a single byte from the file is read and returns it as an integer value. When the end of file is encounted, it returns -1

int FileStream.Read(byte[] buf, int offset, int numBytes)
Read() attempts to read up to numBytes bytes into buf starting at buf[offset]. It retuns the number of bytes successfully read.

Write to a File

void FileStream.WriteByte(byte value)
Writes a byte specified by value to the file. If an error occurs during the write, an IOException will be thrown.

void FileStream.Write(byte[] buf, int offset, int numBytes)
An array of bytes can be written to a file by calling Write(). It writes numBytes bytes from the array buf, beginning at buf[offset] to the file.

void FileStream.Flush()
Output is sometimes not immediately written to the file. It is buffered. To cause data to be written to files whether the buffer is full, call the Flush() method.
Output is

This page is powered by Blogger. Isn't yours?