Download presentation
Presentation is loading. Please wait.
1
Advanced .NET Programming I 8th Lecture
Pavel Ježek 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 (
2
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.i4.2 IL_0002: add IL_0003: ldc.i4.s 10 IL_0005: mul IL_0006: stloc.0 IL_0007: br.s IL_0009 IL_0009: ldloc.0 IL_000a: ret
3
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 Compile time generation IL_0000: ldarg.0 IL_0001: ldc.i4.2 IL_0002: add IL_0003: ldc.i4.s 10 IL_0005: mul IL_0006: stloc.0 IL_0007: br.s IL_0009 IL_0009: ldloc.0 IL_000a: ret new LambdaExpression( new BinaryExpression( ParameterExpression(“value”) ConstantExpression(2) ) ConstantExpression(10)
4
Expression Trees Classes inheriting from Expression (since .NET 3.5):
System.Linq.Expressions.BinaryExpression System.Linq.Expressions.ConditionalExpression System.Linq.Expressions.ConstantExpression System.Linq.Expressions.InvocationExpression System.Linq.Expressions.LambdaExpression System.Linq.Expressions.MemberExpression System.Linq.Expressions.MethodCallExpression System.Linq.Expressions.NewExpression System.Linq.Expressions.NewArrayExpression System.Linq.Expressions.MemberInitExpression System.Linq.Expressions.ListInitExpression System.Linq.Expressions.ParameterExpression System.Linq.Expressions.TypeBinaryExpression System.Linq.Expressions.UnaryExpression New classes inheriting from Expression (since .NET 4.0): System.Linq.Expressions.BlockExpression System.Linq.Expressions.LoopExpression System.Linq.Expressions.TryExpression …
5
Expression Trees and LINQ
6
Lambda Expressions as Expression Trees
value => (value + 2) * 10 Func<int, int> f = Expression<Func<int, int>> e = Compile time generation Compile time generation IL_0000: ldarg.0 IL_0001: ldc.i4.2 IL_0002: add IL_0003: ldc.i4.s 10 IL_0005: mul IL_0006: stloc.0 IL_0007: br.s IL_0009 IL_0009: ldloc.0 IL_000a: ret new LambdaExpression( new BinaryExpression( ParameterExpression(“value”) ConstantExpression(2) ) ConstantExpression(10) Runtime time generation by JIT machine code (e.g. x86) (code actually executed by real CPU)
7
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 Compile time generation IL_0000: ldarg.0 IL_0001: ldc.i4.2 IL_0002: add IL_0003: ldc.i4.s 10 IL_0005: mul IL_0006: stloc.0 IL_0007: br.s IL_0009 IL_0009: ldloc.0 IL_000a: ret new LambdaExpression( new BinaryExpression( ParameterExpression(“value”) ConstantExpression(2) ) ConstantExpression(10) Runtime time generation f = e.Compile(); Runtime time generation by JIT machine code (e.g. x86) (code actually executed by real CPU)
8
Expression Trees – Hello world!
Dynamically creating an expression tree for () => Console.WriteLine(“Hello world!”) lambda expression: delegate void VoidDelegate(); class Program { static void Main(string[] args) { MethodInfo mi = typeof(Console).GetMethod( "WriteLine", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string) }, null ); Expression<VoidDelegate> expr = Expression.Lambda<VoidDelegate>( Expression.Call(mi, Expression.Constant("Hello world!") ) VoidDelegate d = expr.Compile(); d(); }
9
Expression Trees – Another Example
delegate void Void1Delegate(int value); Console.Write("Enter a number: "); int number = int.Parse(Console.ReadLine()); MethodInfo mi = typeof(Console).GetMethod( "WriteLine", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string), typeof(object) }, null ); ParameterExpression param = Expression.Parameter(typeof(int), "valueToAdd"); Expression<Void1Delegate> expr = Expression.Lambda<Void1Delegate>( Expression.Call( mi, Expression.Constant("Hello world! Value is {0}"), Expression.Convert( Expression.Add( param, Expression.Constant(number, typeof(int)) ), typeof(object) ) param Void1Delegate d = expr.Compile(); d(10); d(20);
10
Implementing Generic Complex, etc.
struct IntWrapper { public int v; public IntWrapper(int value) { v = value; } public static IntWrapper operator +(IntWrapper a, IntWrapper b) { return new IntWrapper(a.v + b.v);
11
Implementing Generic Complex, etc. (a Problem)
struct IntWrapper { public int v; public IntWrapper(int value) { v = value; } public static IntWrapper operator +(IntWrapper a, IntWrapper b) { return new IntWrapper(a.v + b.v); Cannot be rewritten to: struct Wrapper<T> { public T v; public Wrapper(T value) { public static Wrapper<T> operator +(Wrapper<T> a, Wrapper<T> b) { return new Wrapper<T>(a.v + b.v);
12
Implementing Generic Complex, etc. (using ExprTree)
using System.Linq.Expressions; struct ValueWrapper<T> { public T v; private static Func<T, T, T> addProxy; static ValueWrapper() { // Creates (a, b) => a + b lambda expression at runtime ParameterExpression paramA = Expression.Parameter(typeof(T), "a"); ParameterExpression paramB = Expression.Parameter(typeof(T), "b"); BinaryExpression addExpr = Expression.Add(paramA, paramB); addProxy = Expression.Lambda<Func<T, T, T>>(addExpr, paramA, paramB).Compile(); } public ValueWrapper(T value) { v = value; public static ValueWrapper<T> operator +(ValueWrapper<T> a, ValueWrapper<T> b) { return new ValueWrapper<T>(addProxy(a.v, b.v));
13
Implementing Generic Complex, etc. (using ExprTree)
using System.Linq.Expressions; struct ValueWrapper<T> { public T v; private static Func<T, T, T> addProxy; static ValueWrapper() { // Creates (a, b) => a + b lambda expression at runtime ParameterExpression paramA = Expression.Parameter(typeof(T), "a"); ParameterExpression paramB = Expression.Parameter(typeof(T), "b"); BinaryExpression addExpr = Expression.Add(paramA, paramB); addProxy = Expression.Lambda<Func<T, T, T>>(addExpr, paramA, paramB).Compile(); } public ValueWrapper(T value) { v = value; public static ValueWrapper<T> operator +(ValueWrapper<T> a, ValueWrapper<T> b) { return new ValueWrapper<T>(addProxy(a.v, b.v));
14
CIL/MSIL Code
15
Reflection.Emit 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 AssemblyBuilder to define assemblies ModuleBuilder to define modules TypeBuilder to define types MethodBuilder to define methods ILGenerator to emit IL-code Überblick
16
Example Reflection.Emit (1)
Creation of a new assembly and module Definition of a new type Definition of a new method with parameter and return types public class HelloWorld { public virtual string SayHelloTo(string name) { return “Hello “ + name; } AssemblyName assemblyName = new AssemblyName(); assemblyName.Name = "HelloWorldAssembly"; AssemblyBuilder newAssembly = Thread.GetDomain().DefineDynamicAssembly( assemblyName, AssemblyBuilderAccess.RunAndSave); ModuleBuilder newModule = newAssembly.DefineDynamicModule("HelloWorldModule"); TypeBuilder newType = newModule.DefineType ("HelloWorld", TypeAttributes.Public); Type[] paramTypes = new Type[] { typeof(string) }; Type retType = typeof(string); MethodBuilder newMethod = newType.DefineMethod("SayHelloTo", MethodAttributes.Public | MethodAttributes.Virtual, retType, paramTypes); Überblick
17
Example Reflection.Emit (2)
Defining the MSIL code for the new method Creating the new type Creating an instance of the new type and calling SayHelloTo method ILGenerator ilGen = newMethod.GetILGenerator (); ilGen.Emit (OpCodes.Ldstr, "Hello "); ilGen.Emit (OpCodes.Ldarg_1); Type t = Type.GetType ("System.String"); MethodInfo mi = t.GetMethod ("Concat", new Type[] { typeof(string), typeof(string) }); ilGen.Emit (OpCodes.Call, mi); ilGen.Emit (OpCodes.Ret); newType.CreateType(); Activator: Contains methods to create types of objects locally or remotely, or obtain references to existing remote objects. MethodInfo method = newType.GetMethod ("SayHelloTo", new Type[] {typeof(string)}); object obj = Activator.CreateInstance (newType); object ret = method.Invoke (obj, new object[] { "Jack" }); Console.WriteLine (ret); Hello Jack Überblick
18
Reflection.Emit -> RegEx
19
Mono.Cecil
Similar presentations
© 2024 SlidePlayer.com Inc.
All rights reserved.