Reflection & Attributes in C#
Reflection & Attributes in C#
Reflection & Attributes in C#
Objectives
Provide an introduction to .NET Reflection Explain how applications can use Reflection to explore type information and how they can build types at runtime
Contents
Section 1: Overview Section 2: Exploring Metadata Section 3: Detail Information Section 4: Building Types at Runtime Section 5: Putting it together Summary
Section 1: Overview
.NET Compile-Execution Cycle .NET Reflection Core Concepts
Reflection Overview
All types in the CLR are self-describing
CLR provides a reader and writer for type definitions
System.Reflection & System.Reflection.emit
You can read programs You can map between type systems You can interrogate objects and types inside a running program
Serialization
Code Generation Analysis, Documentation
Metadata uses
Allows type developed in a PL to be used by code in other PL GC uses to traverse objects Serialization (essential for Web Services) IDE (e.g. IntelliSense)
Type Reflection
Savings.BaseType ==Account Savings.BaseType.BaseType == Object
Object
IEnquire
Account
IPrint IXfer
Savings
System.Object
Assembly
Module
MemberInfo
ParameterInfo
System.Type
MethodBase
FieldInfo
PropertyInfo
EventInfo
MethodInfo
ConstructorInfo
Serialization
Solutions
Inherit from a base type:
class Point : Serializable { } but base type does not know derived type requires multiple inheritance
Solution: Attributes
[Serializable] public class Point : { public double x; public double y; [NonSerialized] public double length; // computed from x, y };
Reflection Emit
Abstractions correspond closely to the CTS that underlies the CLR:
Assemblybuilder ConstructorBuilder CustomAttributeBuilder EnumBuilder EventBuilder FieldBuilder ILGenerator Label LocalBuilder MethodBuilder ModuleBuilder ParameterBuilder PropertyBuilder TypeBuilder
System.Type
Access to meta-data for any .NET type Returned by System.Object.GetType() Allows drilling down into all facets of a type
Category: Simple, Enum, Struct or Class Methods and Constructors, Parameters and Return Fields and Properties, Arguments and Attributes Events, Delegates and Namespaces
Abstract or Implementation?
IsAbstract
Covers all possible properties of a managed type Very intuitive API, no "Parameter Hell"
COM Objects?
IsCOMObject
More
IsUnicodeClass IsSpecialName, etc.
MemberInfo
Base class for all "member" element descriptions
Fields, Properties, Methods, etc.
MemberInfo
MethodBase
ParameterInfo
MethodInfo
ConstructorInfo
FieldInfo, PropertyInfo
FieldInfo
Field data type and attributes Static or Instance field, protection level Can set value through reflection
Provides low-level, direct access with SetValueDirect()
PropertyInfo
Property type and attributes Test methods for readability, writeability "get" and "set" MethodInfo Indexer ParameterInfo Can invoke "set" and "get" through Reflection
MethodInfo, ConstructorInfo
MethodInfo
Return type and attributes List of all parameters as ParameterInfo array Detail implementation information through flag-field Can invoke method through Reflection
ConstructorInfo
Same features as MethodInfo, just for constructors
Attributes
Custom attributes are the killer-app for Reflection! Attributes enable declarative behavior Attributes allow data augmentation
Custom Attributes
[BugFix(121,GA","01/03/05")] [BugFix(107,GA","01/04/05", Comment="Fixed off by one errors")] public class MyMath { public double DoFunc1(double param1) { return param1 + DoFunc2(param1); } public double DoFunc2(double param1) { return param1 / 3; } }
Using Attributes
MyMath mm = new MyMath( ); Console.WriteLine("Calling DoFunc(7). Result: {0}", mm.DoFunc1(7)); // get the member information and use it to retrieve the custom attributes System.Reflection.MemberInfo inf = typeof(MyMath); BugFixAttribute[] attributes = (BugFixAttribute[])inf.GetCustomAttributes(typeof(BugFixAttribute), false); // iterate through the attributes, retrieving the properties foreach(BugFixAttribute attribute in attributes) { Console.WriteLine("\nBugID: {0}", attribute.BugID); Console.WriteLine("Programmer: {0}", attribute.Programmer); Console.WriteLine("Date: {0}", attribute.Date); Console.WriteLine("Comment: {0}", attribute.Comment); } Output: Calling DoFunc(7). Result: 9.33 BugID: 121 Programmer: GA Date: 01/03/05 Comment: BugID: 107 Programmer: GA Date: 01/04/05 Comment: Fixed off by one errors