Advanced NET Programming I 9 th Lecture http

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

Advanced. NET Programming I 9 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)

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: ldarg. 0 IL_0001: ldc. i 4. 2 IL_0002: add IL_0003: ldc. i 4. s 10 IL_0005: mul IL_0006: stloc. 0 IL_0007: br. s IL_0009: ldloc. 0 IL_000 a: ret

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 = Compile time generation IL_0000: ldarg. 0 IL_0001: ldc. i 4. 2 IL_0002: add IL_0003: ldc. i 4. s 10 IL_0005: mul IL_0006: stloc. 0 IL_0007: br. s IL_0009: ldloc. 0 IL_000 a: ret Expression<Func<int, int>> e = 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 = Compile time generation IL_0000: ldarg. 0 IL_0001: ldc. i 4. 2 IL_0002: add IL_0003: ldc. i 4. s 10 IL_0005: mul IL_0006: stloc. 0 IL_0007: br. s IL_0009: ldloc. 0 IL_000 a: ret Runtime generation by JIT machine code (e. g. x 86) (code actually executed by real CPU) Expression<Func<int, int>> e = 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: ldarg. 0 IL_0001: ldc. i 4. 2 IL_0002: add IL_0003: ldc. i 4. s 10 IL_0005: mul IL_0006: stloc. 0 IL_0007: br. s IL_0009: ldloc. 0 IL_000 a: ret 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();

Expression Trees – Hello world! Dynamically creating an expression tree for () => Console.

Expression Trees – Hello world! Dynamically creating an expression tree for () => Console. Write. Line(“Hello world!”) lambda expression: delegate void Void. Delegate(); class Program { static void Main(string[] args) { Method. Info mi = typeof(Console). Get. Method( "Write. Line", Binding. Flags. Public | Binding. Flags. Static, null, new Type[] { typeof(string) }, null ); Expression<Void. Delegate> expr = Expression. Lambda<Void. Delegate>( Expression. Call(mi, Expression. Constant("Hello world!") ) ); Void. Delegate d = expr. Compile(); d(); } }

Expression Trees – Another Example delegate void Void 1 Delegate(int value); Console. Write("Enter a

Expression Trees – Another Example delegate void Void 1 Delegate(int value); Console. Write("Enter a number: "); int number = int. Parse(Console. Read. Line()); Method. Info mi = typeof(Console). Get. Method( "Write. Line", Binding. Flags. Public | Binding. Flags. Static, null, new Type[] { typeof(string), typeof(object) }, null ); Parameter. Expression param = Expression. Parameter(typeof(int), "value. To. Add"); Expression<Void 1 Delegate> expr = Expression. Lambda<Void 1 Delegate>( Expression. Call( mi, Expression. Constant("Hello world! Value is {0}"), Expression. Convert( Expression. Add( param, Expression. Constant(number, typeof(int)) ), typeof(object) ) ), param ); Void 1 Delegate d = expr. Compile(); d(10); d(20);

Implementing Generic Complex, etc. struct Int. Wrapper { public int v; public Int. Wrapper(int

Implementing Generic Complex, etc. struct Int. Wrapper { public int v; public Int. Wrapper(int value) { v = value; } public static Int. Wrapper operator +(Int. Wrapper a, Int. Wrapper b) { return new Int. Wrapper(a. v + b. v); } }

Implementing Generic Complex, etc. (a Problem) struct Int. Wrapper { public int v; public

Implementing Generic Complex, etc. (a Problem) struct Int. Wrapper { public int v; public Int. Wrapper(int value) { v = value; } public static Int. Wrapper operator +(Int. Wrapper a, Int. Wrapper b) { return new Int. Wrapper(a. v + b. v); } } Cannot be rewritten to: struct Wrapper<T> { public T v; public Wrapper(T value) { v = value; } public static Wrapper<T> operator +(Wrapper<T> a, Wrapper<T> b) { return new Wrapper<T>(a. v + b. v); } }

Implementing Generic Complex, etc. (using Expr. Tree) using System. Linq. Expressions; struct Value. Wrapper<T>

Implementing Generic Complex, etc. (using Expr. Tree) using System. Linq. Expressions; struct Value. Wrapper<T> { public T v; private static Func<T, T, T> add. Proxy; static Value. Wrapper() { // Creates (a, b) => a + b lambda expression at runtime Parameter. Expression param. A = Expression. Parameter(typeof(T), "a"); Parameter. Expression param. B = Expression. Parameter(typeof(T), "b"); Binary. Expression add. Expr = Expression. Add(param. A, param. B); add. Proxy = Expression. Lambda<Func<T, T, T>>(add. Expr, param. A, param. B). Compile(); } public Value. Wrapper(T value) { v = value; } public static Value. Wrapper<T> operator +(Value. Wrapper<T> a, Value. Wrapper<T> b) { return new Value. Wrapper<T>(add. Proxy(a. v, b. v)); } }

Implementing Generic Complex, etc. (using Expr. Tree) using System. Linq. Expressions; struct Value. Wrapper<T>

Implementing Generic Complex, etc. (using Expr. Tree) using System. Linq. Expressions; struct Value. Wrapper<T> { public T v; private static Func<T, T, T> add. Proxy; static Value. Wrapper() { // Creates (a, b) => a + b lambda expression at runtime Parameter. Expression param. A = Expression. Parameter(typeof(T), "a"); Parameter. Expression param. B = Expression. Parameter(typeof(T), "b"); Binary. Expression add. Expr = Expression. Add(param. A, param. B); add. Proxy = Expression. Lambda<Func<T, T, T>>(add. Expr, param. A, param. B). Compile(); } public Value. Wrapper(T value) { v = value; } public static Value. Wrapper<T> operator +(Value. Wrapper<T> a, Value. Wrapper<T> b) { return new Value. Wrapper<T>(add. Proxy(a. v, b. v)); } }

CIL/MSIL Code

CIL/MSIL Code

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores have implicit source (register on top) Arithmetic instructions have all operands implicit (n-nary operation takes n registers from top) CPU registers ? ? ? ? R 15 R 14 R 13 R 12 R 11 R 10 R 9 R 8 R 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 Reg. Stack. Top Flags (SP) IP LOAD 2 LOAD 4 ADD LOAD 1 ADD LOAD $F 7 NOT MUL ADD STORE x Disassembled machine code memory

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores have implicit source (register on top) Arithmetic instructions have all operands implicit (n-nary operation takes n registers from top) CPU registers ? ? ? ? 2 IP R 15 R 14 R 13 R 12 R 11 R 10 R 9 R 8 R 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 Reg. Stack. Top Flags (SP) IP LOAD 2 LOAD 4 ADD LOAD 1 ADD LOAD $F 7 NOT MUL ADD STORE x Disassembled machine code memory

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores have implicit source (register on top) Arithmetic instructions have all operands implicit (n-nary operation takes n registers from top) CPU registers ? ? ? ? 4 2 R 15 R 14 R 13 R 12 R 11 R 10 R 9 R 8 R 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 IP Reg. Stack. Top Flags (SP) IP LOAD 2 LOAD 4 ADD LOAD 1 ADD LOAD $F 7 NOT MUL ADD STORE x memory

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores have implicit source (register on top) Arithmetic instructions have all operands implicit (n-nary operation takes n registers from top) CPU registers ? ? ? ? 4 2 R 15 R 14 R 13 R 12 R 11 R 10 R 9 R 8 R 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 IP Reg. Stack. Top Flags (SP) IP LOAD 2 LOAD 4 ADD LOAD 1 ADD LOAD $F 7 NOT MUL ADD STORE x memory

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores have implicit source (register on top) Arithmetic instructions have all operands implicit (n-nary operation takes n registers from top) CPU registers ? ? ? ? 4 6 R 15 R 14 R 13 R 12 R 11 R 10 R 9 R 8 R 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 IP Reg. Stack. Top Flags (SP) IP LOAD 2 LOAD 4 ADD LOAD 1 ADD LOAD $F 7 NOT MUL ADD STORE x memory

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores have implicit source (register on top) Arithmetic instructions have all operands implicit (n-nary operation takes n registers from top) CPU registers ? ? ? ? 1 6 R 15 R 14 R 13 R 12 R 11 R 10 R 9 R 8 R 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 IP Reg. Stack. Top Flags (SP) IP LOAD 2 LOAD 4 ADD LOAD 1 ADD LOAD $F 7 NOT MUL ADD STORE x memory

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores have implicit source (register on top) Arithmetic instructions have all operands implicit (n-nary operation takes n registers from top) CPU registers ? ? ? ? 1 1 6 R 15 R 14 R 13 R 12 R 11 R 10 R 9 R 8 R 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 IP Reg. Stack. Top Flags (SP) IP LOAD 2 LOAD 4 ADD LOAD 1 ADD LOAD $F 7 NOT MUL ADD STORE x memory

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores have implicit source (register on top) Arithmetic instructions have all operands implicit (n-nary operation takes n registers from top) CPU registers ? ? ? ? 1 1 6 R 15 R 14 R 13 R 12 R 11 R 10 R 9 R 8 R 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 IP Reg. Stack. Top Flags (SP) IP LOAD 2 LOAD 4 ADD LOAD 1 ADD LOAD $F 7 NOT MUL ADD STORE x memory

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores have implicit source (register on top) Arithmetic instructions have all operands implicit (n-nary operation takes n registers from top) CPU registers ? ? ? ? 1 2 6 R 15 R 14 R 13 R 12 R 11 R 10 R 9 R 8 R 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 IP Reg. Stack. Top Flags (SP) IP LOAD 2 LOAD 4 ADD LOAD 1 ADD LOAD $F 7 NOT MUL ADD STORE x memory

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores have implicit source (register on top) Arithmetic instructions have all operands implicit (n-nary operation takes n registers from top) CPU registers ? ? ? ? $F 7 2 6 R 15 R 14 R 13 R 12 R 11 R 10 R 9 R 8 R 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 IP Reg. Stack. Top Flags (SP) IP LOAD 2 LOAD 4 ADD LOAD 1 ADD LOAD $F 7 NOT MUL ADD STORE x memory

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores have implicit source (register on top) Arithmetic instructions have all operands implicit (n-nary operation takes n registers from top) CPU registers ? ? ? ? $F 7 2 6 R 15 R 14 R 13 R 12 R 11 R 10 R 9 R 8 R 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 IP Reg. Stack. Top Flags (SP) IP LOAD 2 LOAD 4 ADD LOAD 1 ADD LOAD $F 7 NOT MUL ADD STORE x memory

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores have implicit source (register on top) Arithmetic instructions have all operands implicit (n-nary operation takes n registers from top) CPU registers ? ? ? ? 8 2 6 R 15 R 14 R 13 R 12 R 11 R 10 R 9 R 8 R 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 IP Reg. Stack. Top Flags (SP) IP LOAD 2 LOAD 4 ADD LOAD 1 ADD LOAD $F 7 NOT MUL ADD STORE x memory

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores have implicit source (register on top) Arithmetic instructions have all operands implicit (n-nary operation takes n registers from top) CPU registers ? ? ? ? 8 2 6 R 15 R 14 R 13 R 12 R 11 R 10 R 9 R 8 R 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 IP Reg. Stack. Top Flags (SP) IP LOAD 2 LOAD 4 ADD LOAD 1 ADD LOAD $F 7 NOT MUL ADD STORE x memory

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores have implicit source (register on top) Arithmetic instructions have all operands implicit (n-nary operation takes n registers from top) CPU registers ? ? ? ? 8 16 6 R 15 R 14 R 13 R 12 R 11 R 10 R 9 R 8 R 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 IP Reg. Stack. Top Flags (SP) IP LOAD 2 LOAD 4 ADD LOAD 1 ADD LOAD $F 7 NOT MUL ADD STORE x memory

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores have implicit source (register on top) Arithmetic instructions have all operands implicit (n-nary operation takes n registers from top) CPU registers ? ? ? ? 8 16 6 R 15 R 14 R 13 R 12 R 11 R 10 R 9 R 8 R 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 IP Reg. Stack. Top Flags (SP) IP LOAD 2 LOAD 4 ADD LOAD 1 ADD LOAD $F 7 NOT MUL ADD STORE x memory

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores have implicit source (register on top) Arithmetic instructions have all operands implicit (n-nary operation takes n registers from top) CPU registers ? ? ? ? 8 16 22 R 15 R 14 R 13 R 12 R 11 R 10 R 9 R 8 R 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 IP Reg. Stack. Top Flags (SP) IP LOAD 2 LOAD 4 ADD LOAD 1 ADD LOAD $F 7 NOT MUL ADD STORE x memory

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores have implicit source (register on top) Arithmetic instructions have all operands implicit (n-nary operation takes n registers from top) CPU registers ? ? ? ? 8 16 22 R 15 R 14 R 13 R 12 R 11 R 10 R 9 R 8 R 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 IP Reg. Stack. Top Flags (SP) IP LOAD 2 LOAD 4 ADD LOAD 1 ADD LOAD $F 7 NOT MUL ADD STORE x global data: . . . ? address x. . memory

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores

Stack Machine • • Load/store architecture Loads have implicit target (register on top) Stores have implicit source (register on top) Arithmetic instructions have all operands implicit (n-nary operation takes n registers from top) CPU registers ? ? ? ? 8 16 22 R 15 R 14 R 13 R 12 R 11 R 10 R 9 R 8 R 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 IP Reg. Stack. Top Flags (SP) IP LOAD 2 LOAD 4 ADD LOAD 1 ADD LOAD $F 7 NOT MUL ADD STORE x global data: . . . 22 address x. . memory

CIL/MSIL Code

CIL/MSIL Code

Conditional Branch/Jump instruction. A 1 if P then begin instruction. T 11 instruction. T

Conditional Branch/Jump instruction. A 1 if P then begin instruction. T 11 instruction. T 12 instruction. T 21 end else begin instruction. F 11 instruction. F 21 end; instruction. A 2 if P then JMP x ↓ if P then JMP x else NOP instruction. A 1 if not(P) then JMP else. Branch; instruction. T 11 instruction. T 12 instruction. T 21 JMP end. If; else. Branch: instruction. F 11 instruction. F 21 end. If: instruction. A 2

CIL/MSIL Code

CIL/MSIL Code

Reflection. Emit allows creation of assemblies and types at run-time creation of assemblies creation

Reflection. Emit allows creation of assemblies and types at run-time creation of assemblies creation of new modules creation of new types creation of symbolic meta-information of existing modules System. Reflection. Emit supports realization of. NET compilers und interpreters Important classes of Reflection. Emit are Assembly. Builder Module. Builder Type. Builder Method. Builder ILGenerator to define assemblies to define modules to define types to define methods to emit IL-code

Example Reflection. Emit (1) Creation of a new assembly and module Assembly. Name assembly.

Example Reflection. Emit (1) Creation of a new assembly and module Assembly. Name assembly. Name = new Assembly. Name(); public class Hello. World { assembly. Name "Hello. World. Assembly"; public virtual string =Say. Hello. To(string name) { Assembly. Builder new. Assembly = Thread. Get. Domain(). Define. Dynamic. Assembly( return “Hello “ + name; assembly. Name, Assembly. Builder. Access. Run. And. Save); } Module. Builder new. Module = } new. Assembly. Define. Dynamic. Module("Hello. World. Module"); Definition of a new type Type. Builder new. Type = new. Module. Define. Type ("Hello. World", Type. Attributes. Public); Definition of a new method with parameter and return types Type[] param. Types = new Type[] { typeof(string) }; Type ret. Type = typeof(string); Method. Builder new. Method = new. Type. Define. Method("Say. Hello. To", Method. Attributes. Public | Method. Attributes. Virtual, ret. Type, param. Types);

Example Reflection. Emit (2) Defining the MSIL code for the new method ILGenerator il.

Example Reflection. Emit (2) Defining the MSIL code for the new method ILGenerator il. Gen = new. Method. Get. ILGenerator (); il. Gen. Emit (Op. Codes. Ldstr, "Hello "); il. Gen. Emit (Op. Codes. Ldarg_1); Type t = Type. Get. Type ("System. String"); Method. Info mi = t. Get. Method ("Concat", new Type[] { typeof(string), typeof(string) }); il. Gen. Emit (Op. Codes. Call, mi); il. Gen. Emit (Op. Codes. Ret); Creating the new type new. Type. Create. Type(); Creating an instance of the new type and calling Say. Hello. To method Method. Info method = new. Type. Get. Method ("Say. Hello. To", new Type[] {typeof(string)}); object obj = Activator. Create. Instance (new. Type); object ret = method. Invoke (obj, new object[] { "Jack" }); Console. Write. Line (ret); Hello Jack

Reflection. Emit -> Reg. Ex

Reflection. Emit -> Reg. Ex

Mono. Cecil

Mono. Cecil