Monday, June 18, 2007

Indexers in C#

C# introduces a new concept known as Indexers which are used for treating an object as an array. The indexers are usually known as smart arrays in C# community. Defining a C# indexer is much like defining properties. We can say that an indexer is a member that enables an object to be indexed in the same way as an array.

this [argument list]
{
get
{
// Get codes goes here
}
set
{
// Set codes goes here
}
}


Where the modifier can be private, public, protected or internal. The return type can be any valid C# types. The 'this' is a special keyword in C# to indicate the object of the current class. The formal-argument-list specifies the parameters of the indexer. The formal parameter list of an indexer corresponds to that of a method, except that at least one parameter must be specified, and that the ref and out parameter modifiers are not permitted. Remember that indexers in C# must have at least one parameter. Other wise the compiler will generate a compilation error.

Example:

// C#: INDEXER
using System;
using System.Collections;
class MyClass
{
private string []data = new string[5];
public string this [int index]
{
get
{
return data[index];
}
set
{
data[index] = value;
}
}
}
class MyClient
{
public static void Main()
{
MyClass mc = new MyClass();
mc[0] = "Hello";
mc[1] = "A3-126";
mc[2] = "Google";
mc[3] = "Irla";
mc[4] = "Mumbai";
Console.WriteLine("{0},{1},{2},{3},{4}",mc[0],mc[1],mc[2],mc[3],mc[4]);
}
}


The indexers in C# can be overloaded just like member functions. The formal parameter list of an indexer defines the signature of the indexer. Specifically, the signature of an indexer consists of the number and types of its formal parameters. The element type is not part of an indexer's signature, nor is the names of the formal parameters. The signature of an indexer must differ from the signatures of all other indexers declared in the same class. C# do not have the concept of static indexers. If we declare an indexer static, the compiler will show a compilation time error.

Indexers & Inheritance

Just like any other class members, indexers can also participate in inheritance. A base class indexer is inherited to the derived class.

//C#: Indexer : Inheritance
using System;
class Base
{
public int this[int indxer]
{
get
{
Console.Write("Base GET");
return 10;
}
set
{
Console.Write("Base SET");
}
}
}
class Derived : Base
{

}
class MyClient
{
public static void Main()
{
Derived d1 = new Derived();
d1[0] = 10;
Console.WriteLine(d1[0]);//Displays 'Base SET Base GET 10'
}
}


Indexers & Polymorphism

A Base class indexer can be polymorphicaly overridden in a Derived class. But remember that the modifiers like virtual, override etc are using at property level, not at accessor level.

//C#: Indexer : Polymorphism
using System;
class Base
{
public virtual int this[int index]
{
get
{
Console.Write("Base GET");
return 10;
}
set
{
Console.Write("Base SET");
}
}
}
class Derived : Base
{
public override int this[int index]
{
get
{
Console.Write("Derived GET");
return 10;
}
set
{
Console.Write("Derived SET");
}
}
}
class MyClient
{
public static void Main()
{
Base b1 = new Derived();
b1[0]= 10;
Console.WriteLine(b1[0]);//Displays 'Derived SET Derived GET 10'
}
}

Abstract Indexers

An indexer inside a class can be declared as abstract by using the keyword abstract. Remember that an abstract indexer in a class carries no code at all. The get/set accessors are simply represented with a semicolon. In the derived class we must implement both set and get assessors.

If the abstract class contains only set accessor, we can implement only set in the derived class.
The following program shows an abstract indexer in action.

//C#: Indexer : Abstract
using System;
abstract class Abstract
{
public abstract int this[int index]
{
get;
set;
}
}
class Concrete : Abstract
{
public override int this[int index]
{
get
{
Console.Write(" GET");
return 10;
}
set
{
Console.Write(" SET");
}
}
}
class MyClient
{
public static void Main()
{
Concrete c1 = new Concrete();
c1[0] = 10;
Console.WriteLine(c1[0]);//Displays 'SET GET 10'
}
}

Indexers & Properties

1. An index is identified by it's signature. But a property is identified it's name.
2. An indexer is always an instance member, but a property can be static also.
3. An indexer is accessed through an element access. But a property is through a member access.

Attributes and Reflection in C#

Attributes provide a powerful way to extend metadata by associating declarative information with C# code. The attribute information is stored with the metadata of the element and can be easily retrieved at runtime using reflection.

Attribute
An attribute is essentially an object that represents the data that is associated with a program element. The element to which an attribute is attached is referred to as the target of that attribute.
Attribute targets can be one of the following:

  • All
  • Assembly
  • Class
  • Constructor
  • Delegate
  • Enum
  • Event
  • Field
  • Interface
  • Method
  • Module
  • Parameter
  • Property
  • ReturnValue
  • Struct

Types of Attributes

Attributes are basically of two types: intrinsic and custom.

Intrinsic Attributes
Intrinsic attributes are supplied as part of the Common Language Runtime, and they are integrated into .NET.

In this example below we use a pre–defined attribute, Obsolete, which marks a program entity as obsolete. The attribute accepts two parameters of which the first is a message and the second a boolean value. If the second parameter is true, the compiler gives an error if the method is invoked, and a warning otherwise

Example: Using the Obsolete Attribute

using System;
public class Test
{
[Obsolete("This method is deprecated. Usethe method Display(string)
instead.", false)]
void Display()
{
}
void Display(string s)
{
}
public static void Main( )
{
Test test = new Test ();
test.Display ();
}
}

Custom Attributes:

Custom attributes are attributes that we create for our own purposes. Attributes are public classes and are initialized using constructors. Every attribute must have at least one constructor. The constructors can be overloaded to allow the attribute to be applied to the class in multiple ways.

To create a custom attribute, we have to derive our new custom Attribute class from the class System.Attribute, as shown below.

Example: Declaring a Custom Attribute Class

using System;
public class Comments : Attribute
{
}

Next, we have to specify the target of the attribute using the AttributeUsage attribute. An attribute is applied to the target by specifying the attribute name in brackets as shown in the example below.

Example: Declaring the Custom Attribute Class

public class Comments : System.Attribute[AttributeUsage(AttributeTargets.Class
AttributeTargets.Constructor
AttributeTargets.Field
AttributeTargets.Method
AttributeTargets.Property,
AllowMultiple = true)]
AttributeUsage

The scope and target of the attribute can be defined by applying AttributeUsage. It contains three properties, which we can set to specify attributes.

AllowOn
This is a set of flags that indicates the program entities on which the attribute can be placed. Multiple AttributeTargets can also be specified using a bitwise OR operator.

AllowMultiple
AllowMultiple lets you specify whether you can apply multiple instances of a particular attribute to the same element. If AllowMultiple is set to true, then inherited classes will inherit all instances of the attribute from the parent class. The default value for AllowMultiple is false.

Inherited
The Inherited property determines whether the attribute will be inherited by classes that are derived from the classes to which the attribute is applied. The default value for Inherited is true, indicating that an attribute applied to the base class will be applied to all its derived classes.

Attribute Parameters
Attributes accept parameters for customization. They take two types of parameters, positional and named.

Positional Parameters
Positional parameters are specified using constructor arguments to the attribute class.

Named Parameters
Named parameters are defined by having a non-static field or property in the attribute class.

Attribute parameter types can be:
bool, byte, char, double, float, int, long, short, string
System.object
System.Type
A public enum
A one-dimensional array of the above types

Implementing a Custom Attribute class

The following section shows a custom attribute class called Comments, the application of the attribute to several entities of a class called Employee, and usage of reflection on this class to retrieve the attributes already specified. In the Comments class, the parameters author, type, and description are compulsory positional parameters and status is an optional named parameter.

Example: Implementing the Custom Attribute Class

using System;
using System.Reflection;
[AttributeUsage( AttributeTargets.All )]
public class Comments : System.Attribute
{
public string author = String.Empty;
public string type = String.Empty;
public string description = String.Empty;
private string status = String.Empty;
public Comments(string author, string type,string description)
{
this.author = author;
this.type = type;
this.description = description;
}
public string Status
{
get
{
return status;
}
set
{
status = value;
}
}
public static void DisplayAttributes(Type t)
{
Comments comments = (Comments) Attribute.GetCustomAttribute(t,typeof
(Comments));
Console.WriteLine("The Author is:{0}." , comments.author);
Console.WriteLine("The Description is:{0}." , comments.description);
System.Console.WriteLine("Class Name:{0}", t.Name);
MethodInfo[] methods = t.GetMethods();
object[] attributes = null;
for (int i = 0, l = methods.GetLength(0); i< mi =" methods[i];" attributes =" mi.GetCustomAttributes(true);" thecomments =" (Comments)attribute;" status = "Complete" employeename =" value;" status = "Complete" basic =" value;" status = "Complete" employee =" new">

Reflection

Reflection provides objects that encapsulate assemblies, modules, and types. It is the process by which a program can inspect metadata information dynamically using the reflection API. Using reflection, we can create instances of a type, bind the type to an existing object, or get the type from an existing object and invoke its methods or access its fields and properties. Reflection is much the same as RTTI of native C++ but with a major difference in that reflection in C# works with managed code and is much more powerful.

The reflection classes are contained in the namespace System.Reflection. The classes in the Reflection namespace, along with the System.Type and System.TypedReference classes, provide support for examining and interacting with the metadata. The abstract base class Type helps access metadata information. The types include the constructors, methods, fields, properties, and events of a class and the module and the assembly in which these are stored.

The System.Reflection namespace defines the following types:

  • Assembly
  • Module
  • Enum
  • MethodInfo
  • ConstructorInfo
  • MemberInfo
  • ParameterInfo
  • Type
  • FieldInfo
  • EventInfo
  • PropertyInfo

Here is a complete example of a class that inspects another class and demonstrates the power of reflection to display the metadata information dynamically.

Example: Reflection in Action

using System;
using System.Reflection;
namespace ReflectionTest
{
public class Employee
{
string name;
public string Name
{
get
{
return name ;
}
set
{
name = value ;
}
}
public Employee()
{
}
public Employee ( string name )
{
this.name = name;
}
public void Display ()
{
}
}
public class Reflect
{
public static void DisplayDetails(Type type)
{
Console.WriteLine ( "Class: " + type) ;
Console.WriteLine ();
Console.WriteLine ( "Namespace: " +type.Namespace ) ;
Console.WriteLine ();
ConstructorInfo[] constructorInfo =
type.GetConstructors( );
Console.WriteLine( "Constructors:--") ;
foreach( ConstructorInfo c in constructorInfo)
{
Console.WriteLine( c ) ;
}

PropertyInfo[] propertyInfo =type.GetProperties( );
Console.WriteLine ();
Console.WriteLine( "Properties:--" );
foreach( PropertyInfo p in propertyInfo )
{
Console.WriteLine( p ) ;
}
MethodInfo[] methodInfo = type.GetMethods( ) ;
Console.WriteLine ();
Console.WriteLine( "Methods:--" ) ;
ParameterInfo[] parameterInfo = null;
foreach( MethodInfo m in methodInfo )
{
Console.WriteLine( "Method Name: "+ m.Name ) ;
parameterInfo = m.GetParameters () ;
foreach ( ParameterInfo p in parameterInfo )
{
Console.WriteLine("Parameter Type:" + p.ParameterType + " Parameter
Name: " + p.Name ) ;
}
}
}
public static void Main ( string[] args )
{
DisplayDetails(typeof(Employee));
}
}
}

Reflection in C#

Reflection:
Reflection is one of the features of .Net Framework and has greater importance during the development of large applications. In brief it is a powerful way of collecting and manipulate information present in application's assemblies and its metadata. Metadata contain all the Type information used by the application. The ability to obtain information at runtime also makes it even more advantageous. When reflection is used along with system type, it allows the developer to get the valuable information about all the types and about the assemblies. We can even create the instances and then invoke various types that are used across the application.

What is Reflection?
Reflection is the ability to find out information about objects, the application details (assemblies), its metadata at run-time.

This allows application to collect information about itself and also manipulate on itself. It can be used effectively to find all the types in an assembly and/or dynamically invoke methods in an assembly. This includes information about the type, properties, methods and events of an object and to invoke the methods of object Invoke method can be used too. With reflection we can dynamically create an instance of a type, bind the type to an existing object, or get the type from an existing object and invoke its methods or access its fields and properties. If Attributes (C#) are used in application, then with help of reflection we can access these attributes. It can be even used to emit Intermediate Language code dynamically so that the generated code can be executed directly.

How to use Reflection in our applications?
System.Reflection namespace contains all the Reflection related classes. These classes are used to get information from any of the class under .NET framework. The Type class is the root of all reflection operations. Type is an abstract base class that acts as means to access metadata though the reflection classes. Using Type object, any information related to methods, implementation details and manipulating information can be obtained. The types include the constructors, methods, fields, properties, and events of a class, along with this the module and the assembly in which these information are present can be accessed and manipulated easily.
As mentioned earlier, we can use reflection to dynamically create an instance of any type, bind the type to an existing object, or get the type from an existing object. Once this is done appropriate method can be invoked, access the fields and properties. This can be done by specifying the Type of object or by specifying both assembly and Type of the object that needs to be created. By this the new object created acts like any other object and associated methods, fields and properties can be easily accessed. With reflection we can also find out about various methods associated with newly created object and how to use these object. To find out the attributes and methods associated with an object we can use the abstract class MemberInfo, this class is available under the namespace System.Reflection.
Reflection can be used in following different ways to get different information about various Types.

All the below mentioned classes are available under the namespace System.Reflection.

Assembly Class can be used to get the information and manipulate the assembly. This class allows us to define and load assemblies, load modules that are listed in the assembly manifest, and locate a type from this assembly and create an instance of it.
Assembly.GetType or Assembly.GetTypes are the two methods that can be used to get the Type object from assemblies that have not been loaded. To these method name of the Type(s) is passed as the parameter. Type.GetType is used similarly as mentioned above only distinction is that here the assemblies are loaded.
Example: The following statement fetches mscorlib assembly information

Assembly assemblyInformation = typeof(Object).Module.Assembly;

// Loads an assembly using its file name
Assembly assemblyInformation = Assembly.LoadFrom("MyApplicationToRu n.exe");

// Fetch the types available in the assembly
Type [] assemblyTypeInformation = assemblyInformation.GetTypes ();

foreach (Type TypeInformation in assemblyTypeInformation)
{
Console.WriteLine (TypeInformation.FullName);
}

As shown above once the Type is obtained, there are many ways you can fetch the information about the members of that type. For example, to find out about all the type's members we can use the Type.GetMembers method, which obtains an array of MemberInfo objects describing each of the members of the current type.
Module Class is used for the reflection of the module. This class is used to get information about parent assembly, classes in the module, all the global methods available in the classes.
ConstructorInfo Class is used for the reflection of a constructor, and used to fetch the information about constructor also constructor can be invoked. Constructor information like name, parameters, access modifiers, and various implementation details (such as abstract or virtual) can be obtained. Class Objects are created when constructor of a ConstructorInfo is invoked this returns either the GetConstructors or GetConstructor method of a Type object.
MethodInfo Class is used to obtain information such as the name, return type, parameters, access modifiers (such as public or private), and implementation details (such as ab,stract or virtual) of a any method inside the class, module, assembly. GetMethods or GetMethod method of a Type are used to on the to obtain the information.
FieldInfo Class, as the name suggest this class is used to get the information such as the name, access modifiers (such as public or private) and implementation details (such as static) of a field. Even to get or set field values of a class.

EventInfo Class is used to fetch the information about name, event-handler data type, custom attributes, declaring type, and reflected type of an event. This class is also used to add or remove event handlers.

PropertyInfo Class is used to fetch the information about the name, data type, declaring type, reflected type, and read-only or writable status of a property. Also we can get or set property values using this class.

ParameterInfo Class is used to fetch the information about parameter's name, data type, whether a parameter is an input or output parameter, and the position of the parameter in a method signature. We can GetParameters method in this class that returns an array of ParameterInfo objects representing the parameters of a method, in order.
Another important namespace is System.Reflection.Emit Namespace. This name space can be used to create the type at run time and invoke as and when required. Basic usage of this namespace is to write the information to appropriate types. System.Reflection.Emit namespace contains classes that can be used by the compiler or tool to emit metadata and Microsoft intermediate language (MSIL). The compiler or script generators basically use this information.