Reflection NET Support for Reflection What is Reflection

  • Slides: 19
Download presentation
Reflection. NET Support for Reflection

Reflection. NET Support for Reflection

What is Reflection • Reflection: the process by which a program can observe and

What is Reflection • Reflection: the process by which a program can observe and modify its own structure and behavior at runtime. • What kind of tasks are specific to Reflection: – Inspection: analyzing objects and types to gather information about their definition and behavior. • Typically this is done with little or no prior knowledge about them. (For instance, in the. NET Framework, everything inherits from System. Object and an object-typed reference is the typical starting point for reflection. ) – Manipulation: uses the information gained through inspection to invoke code dynamically, create new instances of discovered types, or even restructure types and objects on the fly • • Manipulating types and objects at run time incurs a performance penalty when compared to the equivalent operations done statically in the source code ! Reflective capabilities need language and compiler-support (vezi exemplul de la Reflection Pattern – curs sapt 6)

Introduction to. NET Reflection • System. Reflection: namespace containing several types that allow to

Introduction to. NET Reflection • System. Reflection: namespace containing several types that allow to reflect over (parse) the metadata tables in assemblies • What can you do by reflection ? – Enumerate modules and types of an assembly; – For each type, obtain its base type, implemented interfaces, fields, methods, properties, events – Create instances of types, dynamically invoke methods • What you cannot do by reflection: – Get information from the reference metadata tables • You could parse the assembly file directly to extract this type of information (as ILDASM does)

Where to use reflection ? • Class libraries that need to understand a type’s

Where to use reflection ? • Class libraries that need to understand a type’s definition: typical example – Serialization • Late binding: the types and methods an application uses are not known at compile time; – example: application gets at runtime the names of an assembly and the name of a type contained in it. The application loads the assembly, constructs an instance of the type and calls methods on it.

The Reflection Logical Hierarchy Classes that implement metaobjects Class Type is defined in the

The Reflection Logical Hierarchy Classes that implement metaobjects Class Type is defined in the namespace System. All others are defined in System. Reflection

Reflecting Over an Assembly’s Types public class Reflector { public static void Reflect. On.

Reflecting Over an Assembly’s Types public class Reflector { public static void Reflect. On. Assembly(Assembly assem) { Write. Line(0, "Assembly: {0}", assem); // Find Modules foreach (Module m in assem. Get. Modules()) { Write. Line(1, "Module: {0}", m); Example: starting from // Find Types an Assembly foreach (Type t in m. Get. Types()) { metaobject, we can determine the modules Write. Line(2, "Type: {0}", t); that it contains. // Find Members For each module, we foreach (Member. Info mi in t. Get. Members()) can determine the types defined there. Write. Line(3, "{0}: {1}", mi. Member. Type, mi); } } } … C# [Richter] – ex. Chap. 20 }

Get a reference to the executing assembly using System; using System. Reflection; Determines which

Get a reference to the executing assembly using System; using System. Reflection; Determines which assembly contains the method that’s making the call and returns its metaobject class App { static void Main() { Assembly assem = Assembly. Get. Executing. Assembly(); Reflector. Reflect. On. Assembly(assem); } } public class Reflector { … } [Richter] – ex. Chap. 20 C#

Explicitly Loading Assemblies using System; using System. Reflection; class App { static void Main(string[]

Explicitly Loading Assemblies using System; using System. Reflection; class App { static void Main(string[] args) { Console. Write. Line("Loading assembly: {0}", args[0]); Assembly a = Assembly. Load. File(args[0]); Reflector. Reflect. On. Assembly(a); } } public class Reflector { … } Loads an assembly specified by the name of its file. The assembly is loaded as a ”data file” C#

Obtaining a Reference to a System. Type Object • • Reflection can be used

Obtaining a Reference to a System. Type Object • • Reflection can be used to learn about types or to manipulate objects using information available only at runtime, not at compile time How to obtain a reference to a System. Type object: – From a System. Object : defines a method Get. Type which determines the type of the specified object and returns a reference to its metaobject – From System. Type: defines a static method Get. Type(String Name) which checks the calling assembly for the defined type and returns a reference to its metaobject – From System. Module as presented in the example before • What can you do with this reference: – You can query the type’s properties: • • Flags: Is. Public, Is. Abstract, Is. Class. Names: Name, Assembly, Full. Name, Module Base. Type Interfaces that are implemented by this type – You can reflect over the type’s members : • Get. Constructors(), Get. Events(), Get. Fields(), Get. Members(), Get. Methods(), Get. Properties() – You can invoke its methods or set values to its properties • Invoke. Member()

Example demonstrates that Object. Get. Type returns the runtime type of the current instance

Example demonstrates that Object. Get. Type returns the runtime type of the current instance // Get. Type. Example. jsl import System. *; public class My. Base. Class extends Object { } //My. Base. Class public class My. Derived. Class extends My. Base. Class { } //My. Derived. Class public class Test { public static void main(String[] args) { My. Base. Class my. Base = new My. Base. Class(); My. Derived. Class my. Derived = new My. Derived. Class(); Object o = my. Derived; My. Base. Class b = my. Derived; Console. Write. Line("mybase: Type is {0}", my. Base. Get. Type()); Console. Write. Line("my. Derived: Type is {0}", my. Derived. Get. Type()); Console. Write. Line("object o = my. Derived: Type is {0}", o. Get. Type()); Console. Write. Line("My. Base. Class b = my. Derived: Type is {0}", b. Get. Type()); } //main } //Test This code produces the following output: mybase: Type is My. Base. Class my. Derived: Type is My. Derived. Class object o = my. Derived: Type is My. Derived. Class My. Base. Class b = my. Derived: Type is My. Derived. Class [MSDN Library] J#

Reflecting over a type’s members • • Members of a type: Fields, constructors, methods,

Reflecting over a type’s members • • Members of a type: Fields, constructors, methods, properties, events, and nested types. The FCL contains a type called System. Reflection. Member. Info. Can be obtained from Type: method Get. Members() returns an array of Member. Info Table shows some properties and methods offered by the Member. Info type. These properties and methods are common to all type members. Member Name Member Type Description Name String property Name of the member Member. Types (enum) property Returns the kind of member (Fields, constructors, methods, properties, events, and nested types) Declaring. Type property Returns the Type that defined the member (different from Reflected. Type in case of inherited members) Reflected. Type property Returns the type that was used to obtain the member

Hierarchy of the reflection types derived from Member. Info • • • Member. Info

Hierarchy of the reflection types derived from Member. Info • • • Member. Info is abstract Get. Members() method in Type returns an array of elements that are of the concrete subtypes Type offers also specific methods: Get. Fields(), Get. Constructors(), Get. Methods(), Get. Properties(), Get. Events()

Example demonstrates how to retrieve informations about a type’s members // Type. Get. Members.

Example demonstrates how to retrieve informations about a type’s members // Type. Get. Members. Example. jsl class My. Class { public int my. Int = 0; public String my. String = null; public My. Class() { } //My. Class public void Myfunction() { } //Myfunction private void My. Secret() { } //My. Secret } //My. Class class Type_Get. Members { public static void main(String[] args) { My. Class my. Object = new My. Class(); Member. Info my. Member. Info[]; // Get the type of 'My. Class'. Type my. Type = my. Object. Get. Type(); // Get the info related to all public member's of 'My. Class'. my. Member. Info = my. Type. Get. Members(); Console. Write. Line( "n. The members of class '{0}' are : n", my. Type); for (int i = 0; i < my. Member. Info. length; i++) { // Display name and type of the concerned member. Console. Write. Line("'{0}' is a {1}", my. Member. Info[i]. get_Name(), my. Member. Info[i]. get_Member. Type()); } } //main } //Type_Get. Members [MSDN Library] J#

Selecting kinds of reflected members • Get. Members methods can take a Binding. Flags

Selecting kinds of reflected members • Get. Members methods can take a Binding. Flags parameter: – Ignore. Case: Search using case-insensitivity. – Declared. Only: Only search members on the declared type. (Ignore inherited members. ) – Instance: Search instance members. – Static: Search static members. – Public: Search public members. – Non. Public: Search nonpublic members. – Flatten. Hierarchy: Search static members defined by base types. • Code Acess Security and Reflection – Reflection makes it possible to bind to a nonpublic member and invoke the member, allowing application code a way to access private members that a compiler would normally prohibit the code from accessing. – However, reflection uses Code Access Security to ensure that its power isn’t abused or exploited. – Code with the appropriate System. Security. Permissions. Reflection. Permission can have access to the public, protected, and even private members of any loaded Type. – Security Reflection. Permissions in. NET can be set/enforced at assembly and/or type level

Example demonstrates how to retrieve private information class Type_Get. Members { public static void

Example demonstrates how to retrieve private information class Type_Get. Members { public static void main(String[] args) { try { My. Class my. Object = new My. Class(); Member. Info my. Member. Info[]; // Get the type of 'My. Class'. Type my. Type = my. Object. Get. Type(); // Get the info related to all public+private member's of 'My. Class'. Binding. Flags bf = Binding. Flags. Declared. Only | Binding. Flags. Non. Public | Binding. Flags. Instance | Binding. Flags. Static; my. Member. Info = my. Type. Get. Members(bf); Console. Write. Line("n. The members of class '{0}' are : n", my. Type); for (int i = 0; i < my. Member. Info. length; i++) { // Display name and type of the concerned member. Console. Write. Line("'{0}' is a {1}", my. Member. Info[i]. get_Name(), my. Member. Info[i]. get_Member. Type()); } } catch (Security. Exception e) { Console. Write. Line("Exception : " + e. get_Message()); } } //main } //Type_Get. Members [MSDN Library] J#

Creating an Instance of a Type • Once you have a reference to a

Creating an Instance of a Type • Once you have a reference to a Type object, there are several mechanisms to create an instance of this type: – System. Activator: defines several overloaded Create. Instance method that get as parameters a Type object or a string that identifies the type. Creates an instance of the specified type using the constructor that best matches the specified parameter. Returns a reference to the new created Object – System. Reflection. Constructor. Info: defines several overloaded Invoke method that invokes the constructor reflected by this instance. Returns an instance of the class associated with the constructor. – Special cases: • System. Array: static Create. Instance method in Array

Calling a Type’s Members • • Invoke. Member method in Type Several overloaded versions;

Calling a Type’s Members • • Invoke. Member method in Type Several overloaded versions; the maximum of parameters are: public Object Invoke. Member( String name, // Name of member Binding. Flags invoke. Attr, // How to look up members Binder binder, // How to match members and arguments Object target, // Object to invoke member on or null if it is a static member Object[] args, // Arguments to pass to method Culture. Info culture); // Culture used by some binders • Internally, Invoke. Member performs two operations: – Binding: select the appropriate member to be called – Invoking: actually invokes the member • • invoke. Attr: A bitmask comprised of one or more Binding. Flags that specify how the search is conducted. The access can be one of the Binding. Flags such as Public, Non. Public, Private, Create. Instance, Invoke. Method, Get. Field, Set. Field, Declared. Only, Exact. Binding, etc. The type of lookup need not be specified. If the type of lookup is omitted, Binding. Flags. Public| Binding. Flags. Instance will apply. Binder: A Binder object that defines a set of properties and enables binding, which can involve selection of an overloaded method, coercion of argument types, and invocation of a member through reflection. If it is not specified or null, the Default. Binder is used.

Bind once, invoke multiple times • • Every time you call Invoke. Member, it

Bind once, invoke multiple times • • Every time you call Invoke. Member, it must bind to a particular member and then invoke it. Consequence: Having the binder select the right member each time you want to invoke a member is time-consuming. So if you plan on accessing a member frequently, you’re better off binding to the desired member once and then accessing that member as often as you want. You bind to a member (without invoking it) by calling one of the following Type’s methods: Get. Fields, Get. Constructors, Get. Methods, Get. Properties, Get. Events methods, or any similar method. All these methods return references to objects whose type offers methods to access the specific member directly: – – – Field. Info: Get. Value, Set. Value Constructor. Info: Invoke Method. Info: Invoke Property. Info: Get. Value, Set. Value Event. Info: Add. Event. Handler, Remove. Event. Handler

Example demonstrates how to create an instance of a type and call it’s methods

Example demonstrates how to create an instance of a type and call it’s methods // Invoke. Method. jsl import System. *; import System. Reflection. *; class Test. Invoke. Method { public static void main(String[] args) { class My. Class { public int my. Int = 0; public String my. String = null; // get somehow the Type metaobject Type my. Type = Type. Get. Type ("My. Class"); //create instance obj Object obj = Activator. Create. Instance(my. Type); public My. Class() { } //My. Class // bind to method My. Function Method. Info mi = my. Type. Get. Method("My. Function"); // invokes My. Function on obj if (mi!=null) mi. Invoke(obj, null); public void My. Function() { Console. Write. Line("My function"); } //Myfunction private void My. Secret() { Console. Write. Line("My secret"); } } //My. Class mi = my. Type. Get. Method("My. Secret"); if (mi!=null) mi. Invoke(obj, null); } } //main } J#