Advanced NET Programming I 8 th Lecture http

  • Slides: 19
Download presentation
Advanced. NET Programming I 8 th Lecture http: //d 3 s. mff. cuni. cz/~jezek

Advanced. NET Programming I 8 th Lecture http: //d 3 s. mff. cuni. cz/~jezek Pavel Ježek pavel. jezek@d 3 s. mff. cuni. cz CHARLES UNIVERSITY IN PRAGUE faculty of mathematics and physics Some of the slides are based on University of Linz. NET presentations. © University of Linz, Institute for System Software, 2004 published under the Microsoft Curriculum License (http: //www. msdnaa. net/curriculum/license_curriculum. aspx)

Reflection Permits access to meta-information of types at run-time System. Reflection allows: Getting meta-information

Reflection Permits access to meta-information of types at run-time System. Reflection 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 System. Reflection. Emit

Reflection Class Hierarchy Assembly Get. Types() * Base. Type * Interfaces Get. Fields() *

Reflection Class Hierarchy Assembly Get. Types() * Base. Type * Interfaces Get. Fields() * Field. Info Get. Methods() * Method. Info Get. Constructors() * Constructor. Info Get. Properties() * Property. Info Get. Events() * Event. Info Method. Base Member. Info

Class Type used for meta-description of all types in the run-time system Provides access

Class 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 : Member. Info, IReflect { public abstract string Full. Name {get; }; public abstract Type Base. Type {get; }; public Type[] Get. Interfaces(); • Type name • Direct base type • List of implemented interfaces public bool Is. Abstract {get; }; public bool Is. Class {get; }; public bool Is. Public {get; }; … • Properties of type public Constructor. Info[] Get. Constructors(); public virtual Event. Info[] Get. Events(); public Field. Info[] Get. Fields(); public Method. Info[] Get. Methods(); public Property. Info[] Get. Properties(); . . . • Getting constructors, events, fields, methods, properties • Optionally parameterized by Binding. Flags

Example: Handling plug-ins “Plug-in” is any class implementing IMy. Plugin interface string[] files =

Example: Handling plug-ins “Plug-in” is any class implementing IMy. Plugin interface string[] files = Directory. Get. Files(path, "*. dll"); // returns full paths foreach (string f in files) { Assembly a = Assembly. Load. File(f); Type[] types = a. Get. Types(); foreach (Type t in types) { if (t. Is. Class) { if (t. Get. Interface(“IMy. Plugin”) != null) { IMy. Plugin p = (IMy. Plugin) Activator. Create. Instance(t); // add p to list of all installed plug-ins } }

Attributes with Parameters Example ter arame lp ona positi [Obsolete("Use class C 1 instead",

Attributes with Parameters Example ter arame lp ona positi [Obsolete("Use class C 1 instead", Is. Error=true)] public class C {. . . } ters ameters e m a ar p. s e o nam after p e com // 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 Obsolete. Attribute : Attribute { // class name ends with "Attribute" public string Message { get; } // but can be used as "Obsolete" public bool Is. Error { get; set; } public Obsolete. Attribute() {. . . } public Obsolete. Attribute(string msg, bool error) {. . . } } Valid variants: [Obsolete] [Obsolete("some Message")] [Obsolete("some Message", false)] [Obsolete("some Message", Is. Error=false)] // Message == "", Is. Error == false // Is. Error == false values must be constants

Attribute. Usage describes how user-defined attributes are to be used public class Attribute. Usage.

Attribute. Usage describes how user-defined attributes are to be used public class Attribute. Usage. Attribute : Attribute { public Attribute. Usage. Attribute (Attribute. Targets valid. On) {. . . } public bool Allow. Multiple { get; set; } // default: false public bool Inherited { get; set; } // default: false } Usage [Attribute. Usage(Attribute. Targets. Class | Attribute. Targets. Interface, Allow. Multiple=false)] public class My. Attribute : Attribute {. . . }

Defining Your Own Attributes Declaration [Attribute. Usage(Attribute. Targets. Class | Attribute. Targets. Interface, Inherited=true)]

Defining Your Own Attributes Declaration [Attribute. Usage(Attribute. Targets. Class | Attribute. Targets. Interface, Inherited=true)] class Comment. Attribute : Attribute { string text, author; public string Text { get {return text; } } public string Author { get {return author; } set {author = value; } } public Comment (string text) { this. text = 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 = t. Get. Custom. Attributes(typeof(Comment Attribute), true); foreach (Comment. Attribute ca in a) { Console. Write. Line(ca. Text + ", " + ca. Author); } } }

Reflection Example Print all existing types in a given assembly Type[] types = a.

Reflection Example Print all existing types in a given assembly Type[] types = a. Get. Types(); foreach (Type t in types) Console. Write. Line(t. Full. Name); Hello. World Print all existing methods of a given type Type hw = a. Get. Type("Hello. World"); Method. Info[] methods = hw. Get. Methods(); foreach (Method. Info m in methods) Console. Write. Line(m. Name); Get. Type To. String Equals Get. Hash. Code

Reflection Example Create a new instance of a given type Assembly a = Assembly.

Reflection Example Create a new instance of a given type Assembly a = Assembly. Load("Hello. World"); object o = a. Create. Instance("Hello. World"); Get method To. String(), which has no parameters Invoke the method Type hw = a. Get. Type("Hello. World"); Method. Info mi = hw. Get. Method("To. String"); object ret. Val = mi. Invoke(o, null);

Reflection: Accessing Private Fields using System. Reflection; class Helper. Class { private int private.

Reflection: Accessing Private Fields using System. Reflection; class Helper. Class { private int private. Data; public int Public. Data { get { return private. Data; } set { private. Data = value; } } } class Program { static void Main(string[] args) { Helper. Class hc = new Helper. Class(); hc. Public. Data = 123; Type type = hc. Get. Type(); Field. Info fi = type. Get. Field("private. Data", Binding. Flags. Instance | Binding. Flags. Non. Public); Console. Write. Line(fi. Get. Value(hc)); fi. Set. Value(hc, 456); Console. Write. Line(hc. Public. Data); } }

Reflection: Accessing Private Fields using System. Reflection; class Helper. Class { private int private.

Reflection: Accessing Private Fields using System. Reflection; class Helper. Class { private int private. Data; public int Public. Data { get { return private. Data; } set { private. Data = value; } } } class Program { WARNING: SLOW & DANGEROUS!!! static void Main(string[] args) { Helper. Class hc = new Helper. Class(); hc. Public. Data = 123; Type type = hc. Get. Type(); Field. Info fi = type. Get. Field("private. Data", Binding. Flags. Instance | Binding. Flags. Non. Public); Console. Write. Line(fi. Get. Value(hc)); fi. Set. Value(hc, 456); Console. Write. Line(hc. Public. Data); } }

MEF

MEF

Lambda Expressions as Delegates • When assigned to a delegate, equivalent code of an

Lambda Expressions as Delegates • When assigned to a delegate, equivalent code of an anonymous method is generated at compile time! value => (value + 2) * 10 Func<int, int> f = Compile time generation IL_0000: IL_0001: IL_0002: IL_0003: IL_0005: IL_0006: IL_0007: IL_0009: IL_000 a: ldarg. 0 ldc. i 4. 2 add ldc. i 4. s mul stloc. 0 br. s ldloc. 0 ret 10 IL_0009

Lambda Expressions as Expression Trees Permit lambda expressions to be represented as data structures

Lambda Expressions as Expression Trees Permit lambda expressions to be represented as data structures instead of executable code Lambda expression convertible to delegate D (assignment causes code generation) is also convertible to expression tree (abstract syntax tree) of type System. Linq. Expressions. Expression<D> (assignment causes expression tree generation – compile time generation of code, that creates the expression tree [class instances] at runtime) Expression trees are immutable value => (value + 2) * 10 Func<int, int> f = Expression<Func<int, int>> e = Compile time generation IL_0000: IL_0001: IL_0002: IL_0003: IL_0005: IL_0006: IL_0007: IL_0009: IL_000 a: ldarg. 0 ldc. i 4. 2 add ldc. i 4. s mul stloc. 0 br. s ldloc. 0 ret 10 IL_0009 Compile time generation new Lambda. Expression( new Binary. Expression( Parameter. Expression(“value”) Constant. Expression(2 ) ) Constant. Expression(10 ) ) )

Expression Trees Classes inheriting from Expression (since. NET 3. 5): System. Linq. Expressions. Binary.

Expression Trees Classes inheriting from Expression (since. NET 3. 5): System. Linq. Expressions. Binary. Expression System. Linq. Expressions. Conditional. Expression System. Linq. Expressions. Constant. Expression System. Linq. Expressions. Invocation. Expression System. Linq. Expressions. Lambda. Expression System. Linq. Expressions. Member. Expression System. Linq. Expressions. Method. Call. Expression System. Linq. Expressions. New. Array. Expression System. Linq. Expressions. Member. Init. Expression System. Linq. Expressions. List. Init. Expression System. Linq. Expressions. Parameter. Expression System. Linq. Expressions. Type. Binary. Expression System. Linq. Expressions. Unary. Expression • New classes inheriting from Expression (since. NET 4. 0): System. Linq. Expressions. Block. Expression System. Linq. Expressions. Loop. Expression System. Linq. Expressions. Try. Expression …

Expression Trees and LINQ

Expression Trees and LINQ

Lambda Expressions as Expression Trees value => (value + 2) * 10 Func<int, int>

Lambda Expressions as Expression Trees value => (value + 2) * 10 Func<int, int> f = Expression<Func<int, int>> e = Compile time generation IL_0000: IL_0001: IL_0002: IL_0003: IL_0005: IL_0006: IL_0007: IL_0009: IL_000 a: ldarg. 0 ldc. i 4. 2 add ldc. i 4. s mul stloc. 0 br. s ldloc. 0 ret 10 IL_0009 Runtime generation by JIT machine code (e. g. x 86) (code actually executed by real CPU) Compile time generation new Lambda. Expression( new Binary. Expression( Parameter. Expression(“value”) Constant. Expression(2 ) ) Constant. Expression(10 ) ) )

Expression Trees to Dynamic Methods (via Implicit Reflection. Emit) Runtime generation of CIL code

Expression Trees to Dynamic Methods (via Implicit Reflection. Emit) Runtime generation of CIL code of a dynamic method from expression tree instance: value => (value + 2) * 10 Func<int, int> f = Expression<Func<int, int>> e = Compile time generation IL_0000: IL_0001: IL_0002: IL_0003: IL_0005: IL_0006: IL_0007: IL_0009: IL_000 a: ldarg. 0 ldc. i 4. 2 add ldc. i 4. s mul stloc. 0 br. s ldloc. 0 ret 10 IL_0009 Compile time generation new Lambda. Expression( new Binary. Expression( Parameter. Expression(“value”) Constant. Expression(2 ) ) Constant. Expression(10 ) ) ) Runtime generation by JIT machine code (e. g. x 86) (code actually executed by real CPU) f = e. Compile();