C# & .
NET
Pavel Jeek
Based on University of Linz .NET presentations. University of Linz, Institute for System Software, 2004 published under the Microsoft Curriculum License ([Link]
Reflection
Permits access to meta-information of types at run-time [Link] allows:
Getting meta-information about assemblies, modules and types Getting meta-information about the members of a type Dynamic creation of instances of a type at run-time Search for methods and their dynamic invocation at run-time Accessing values of properties and fields of an object Design of new types at run time - namespace [Link]
Reflection Class Hierarchy
Assembly GetTypes() * Type * GetFields() GetMethods() Interfaces * FieldInfo * MethodInfo MethodBase MemberInfo BaseType
GetConstructors() * ConstructorInfo GetProperties() GetEvents() * PropertyInfo * EventInfo
Class Assembly
Class Assembly loads assemblies and their meta-data Provides access to its meta-data
public class Assembly { public static Assembly Load(string name); public virtual string FullName {get;} public virtual string Location {get;} public virtual MethodInfo EntryPoint {get;} public Module[] GetModules(); public virtual Type[] GetTypes(); public virtual Type GetType(string typeName); public object CreateInstance(string typeName); ... } Loading an assembly Name, storage location, entry point of the assembly Getting modules and all in the assembly defined types Getting type with name typeName Creation of an object of type typeName
Class Type
Type used for meta-description of all types in the run-time system Provides access to the meta-information about its members
public abstract class Type : MemberInfo, IReflect { public abstract string FullName {get;}; public abstract Type BaseType {get;}; public Type[] GetInterfaces(); public bool IsAbstract {get;}; public bool IsClass {get;}; public bool IsPublic {get;}; public ConstructorInfo[] GetConstructors(); public virtual EventInfo[] GetEvents(); public FieldInfo[] GetFields(); public MethodInfo[] GetMethods(); public PropertyInfo[] GetProperties(); ... Type name Direct base type List of implemented interfaces
Properties of type
Getting constructors, events, fields, methods, properties Optionally parameterized by BindingFlags
Example Reflection
C# program "HelloWorld"
namespace Hello { using System; public class HelloWorld { public static void Main(string[] args) { [Link]("HelloWorld"); } public override string ToString() { return "Example HelloWorld"; }
csc [Link]
[Link]
Loading the assembly "[Link]":
Assembly a = [Link]("HelloWorld");
Example Reflection
Print all existing types in a given assembly
Type[] types = [Link](); foreach (Type t in types) [Link]([Link]);
[Link]
Print all existing methods of a given type
Type hw = [Link]("[Link]"); MethodInfo[] methods = [Link](); foreach (MethodInfo m in methods) [Link]([Link]);
GetType ToString Equals GetHashCode
Attributes with Parameters
Example
te r e m a r nal pa o i t i s po
ters ameters e m para pos. par e m na fter a e com
[Obsolete("Use class C1 instead", IsError=true)] public class C {...}
// causes compiler message saying // that C is obsolete
Positional parameter = parameter of the attribute's constructor Name parameter = a property of the attribute
Attributes are declared as classes
public class ObsoleteAttribute : Attribute { // class name ends with "Attribute" public string Message { get; } // but can be used as "Obsolete" public bool IsError { get; set; } public ObsoleteAttribute() {...} public ObsoleteAttribute(string msg) {...} public ObsoleteAttribute(string msg, bool error) {...} }
Valid variants:
[Obsolete] [Obsolete("some Message")] [Obsolete("some Message", false)] [Obsolete("some Message", IsError=false)] // Message == "", IsError == false // IsError == false
values must be constants
AttributeUsage
AttributeUsage describes how user-defined attributes are to be used
public class AttributeUsageAttribute : Attribute { public AttributeUsageAttribute (AttributeTargets validOn) {...} public bool AllowMultiple { get; set; } // default: false public bool Inherited { get; set; } // default: false }
Usage
[AttributeUsage([Link] | [Link], AllowMultiple=false)] public class MyAttribute : Attribute { ... }
Defining Your Own Attributes
Declaration
[AttributeUsage([Link] | [Link], Inherited=true)] class CommentAttribute : Attribute { string text, author; public string Text { get {return text;} } public string Author { get {return author;} set {author = value;} } public Comment (string text) { [Link] = text; author ="HM"; } }
Usage
[Comment("This is a demo class for Attributes", Author="XX")] class C { ... }
Querying the attribute at runtime
class Attributes { static void Main() { Type t = typeof(C); object[] a = [Link](typeof(Comment), true); foreach (Comment ca = a) { [Link]([Link] + ", " + [Link]); } } }
Example Reflection
Create a new instance of a given type
Assembly a = [Link]("HelloWorld"); object o = [Link]("[Link]");
Get method ToString(), which has no parameters Invoke the method
Type hw = [Link]("[Link]"); MethodInfo mi = [Link]("ToString"); object retVal = [Link](o, null);
Example: Handling plug-ins
Plug-in is any class implementing IMyPlugin interface
string[] files = [Link](path, "*.dll"); // returns full paths foreach (string f in files) { Assembly a = [Link](f); Type[] types = [Link](); foreach (Type t in types) { if ([Link]) { if ([Link](IMyPlugin) != null) { IMyPlugin p = (IMyPlugin) [Link](t); // add p to list of all installed plug-ins } } } }