Declarative programming vs imperative programming :
· A program is "declarative" if it describes what something is like, rather than how to create it.
· Imperative programs explicitly specify an algorithm to achIEve a goal, while declarative programs explicitly specify the goal and leave the implementation of the algorithm to the support software
.Net metadata, in the Microsoft .Net framework, refers to certain data structures embedded within the Common Intermediate Language code that describes the high-level structure of the code. Metadata is the life blood of the .Net platform; Metadata describes all classes and class members that are defined in the assembly, and the classes and class members that the current assembly will call from another assembly. The metadata for a method contains the complete description of the method, including the class (and the assembly that contains the class), the return type and all of the method parameters.
A compiler for the common language runtime (CLR) will generate metadata during compilation and store the metadata (in a binary format) directly into assemblies and modules. Metadata in .NET cannot be underestimated. Metadata allows us to write a component in C# and let another application use the metadata from Visual Basic .NET. The metadata description of a type allows the runtime to layout an object in memory, to enforce security and type safety, and ensure version compatibilities. It makes the assemblIEs in .Net fully self-describing. This allows developers to share components across languages and eliminates the need for header files.
Reflection
Reflection is the ability to read metadata at runtime. Using reflection, it is possible to uncover the methods, propertIEs, and events of a type, and to invoke them dynamically. Reflection also allows us to create new types at runtime.
Custom attribute:
Attributes enhance flexibility in software systems because they promote loose coupling of functionality, custom attribute let users leverage the loose coupling power of attributes for their own purposes.
Developers can add metadata to their code through attributes. There are two types of attributes, custom and pseudo custom attributes.
A custom attribute is a regular class that inherits from the Attribute
class. A custom attribute can be used on any method, property, class or entire assembly with the syntax: [Attribute name(optional parameter, optional name=value pairs)]
as in:
[Custom]
[Custom(1)] [Custom(1), comment="yes"]
Custom attributes are interpreted by application code and not the CLR.When the compiler sees a custom attribute it will generate custom metadata that is not recognised by the CLR. The developer has to provide code to read the metadata and act on it.
class CustomAttribute : Attribute
{
int ParamNumber = 0;
string Comment = "";
public CustomAttribute()
{
}
public CustomAttribute(int num)
{
ParamNumber = num;
}
public String comment
{
set { Comment = value; }
}
}
The Visual C# compiler automatically adds the string "attribute" at the end of any attribute name. Consequently, every class implementing the handling of an attribute must end with this string but usage of this string is optional when using the attribute.
Using the attribute invokes the constructor of the class. Overloaded constructors are supported. Name-Value pairs are mapped to properties, the name denotes the name of the property and the value supplIEd is set by the property
Assemblies contain tables of metadata. These tables are described by the CIL specification. The metadata tables will have zero or more entrIEs and the position of an entry determines its index. When CIL code uses metadata it does so through a metadata token. This is a 32-bit value where the top 8 bits identify the appropriate metadata table, and the remaining 24 bits give the index of the metadata in the table, We can see metadata tables by ildasm: ildasm /metadata=RAW CustomAttributeTest.exe
Standard Attribute:
public class SomeWebService : System.Web.Services.WebService
{
[WebMethod]
public DataSet GetDailySales()
{
return null;
// code to process the request...
}
}
Custom Attributes vs. Class PropertIEs
An attribute takes the same "shape and form" as a property when you define it, but you can attach it to all manner of different assembly level types—not just Classes. following table lists all the assembly level types that you can apply attributes to.
Assembly, Class, Delegate, Enum, Event, Interface, Method, Module, Parameter, Constructor, FIEld, Property, ReturnValue, Structure
Querying for our Custom Attribute
Once we have associated our attribute with various source code elements, we can query the metadata of these elements at run-time by using the .Net Framework Reflection classes. Reflection can be used to gain information about every ASPect of our class or assembly, including the class or assembly it.
First we need to extract the metadata for our class, which we do by using the typeof function :-
Type type = typeof(AttributeClass);
The custom attribute information is retrIEved into an object array by calling the Type.GetCustomAttributes() function. The method signatures for both overloaded versions are as follows:-
public object[] GetCustomAttributes(
bool inherit //Search the members inheritance heirarchy
);
public object[] GetCustomAttributes(
Type attributeType, //Type of attribute to search for.
bool inherit //Search the members inheritance heirarchy
We can now retrIEve the attribute information for our class, and loop through this array to obtain information about each attribute:-
object[] attributes = type.GetCustomAttributes(true);
foreach (object attribute in attributes) {
Console.Write(" {0}", attribute.ToString());
DescriptionAttribute da = attribute as DescriptionAttribute;
if (da != null)
Console.WriteLine(".Description={0}", da.Description);
else
Console.WriteLine();
}
Example:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Services;
using System.Data;
using System.Diagnostics;
using System.Reflection;
namespace CustomAttributeTest
{
[Custom(20080808, comment = "TOPSECRET")]
class Program
{
static void Main(string[] args)
{
Old();Color c = Color.blue | Color.red;
Console.WriteLine(c.ToString());
SomeClass sc = new SomeClass();
sc.UnitTest();
System.Console.WriteLine("Enter your ID");
string s = Console.ReadLine();
int j = System.Int32.Parse(s);
if (IsValid(j) == true)
{
Console.WriteLine("Valid user");
}
else
{
Console.WriteLine("Invalid user");
}
Console.ReadLine();
}
[Obsolete("Don''t use Old method, use New method", false)]
static void Old()
{
}
static void New()
{
}
public static bool IsValid([Custom(-1)]int i)
{
Type type = typeof(Program);
CustomAttribute CustAttr;
//Querying Class Attributes
foreach (Attribute attr in type.GetCustomAttributes(true))
{
CustAttr = attr as CustomAttribute;
if (null != CustAttr)
{
return CustAttr.comment == "TOPSECRET";
}
}
//Querying Class-Method Attributes
foreach (MethodInfo method in type.GetMethods())
{
foreach (Attribute attr in method.GetCustomAttributes(true))
{
CustAttr = attr as CustomAttribute;
if (null != CustAttr)
{
return CustAttr.comment == "TOPSECRET";
}
}
}
if (i > 100)
{
return true;
}
//Querying Class Attributes
foreach (Attribute attr in type.GetCustomAttributes(true))
{
CustAttr = attr as CustomAttribute;
if (null != CustAttr)
{
return CustAttr.comment == "TOPSECRET";
} else
{
return false;
}
}
public class SomeWebService : System.Web.Services.WebService
{
[WebMethod(Description = "Sales volume")]
public DataSet GetDailySales()
{
return null;
// code to process the request...
}
}
public class SomeClass
{
[Conditional("DEBUG")]
public void UnitTest()
{
// code to do unit testing...
}
}
[Flags]
enum Color
{
red = 0x001,
blue = 0x002,
green = 0x004,
}
}
\\\\\\\\\\\\\\\\\\\\customattribute.cs\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Diagnostics;
namespace CustomAttributeTest
{
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
public class CustomAttribute : Attribute
{
private int ParamNumber = 0;
private string Comment = "";
public virtual String comment
{
set { this.Comment = value; }
get { return Comment; }
}
public CustomAttribute()
{
}
public CustomAttribute(int num)
{
this.ParamNumber = num;
this.Comment = "comment";
}
}
}