/// <summary> /// Compiles a DynamicMethodState and returns a delegate. /// </summary> /// <typeparam name="R">The return type of the expression</typeparam> /// <typeparam name="C">The type of the function class</typeparam> /// <param name="methodState">The serialized version of a method on the functionClass</param> /// <returns>ExecuteExpression<R, C> - a delegate that calls the compiled expression</returns> public ExecuteExpression <R, C> CreateExpressionDelegate <R, C>(DynamicMethodState methodState) { //create a dynamic method var dynamicMethod = new DynamicMethod("_" + Guid.NewGuid().ToString("N"), typeof(R), new[] { typeof(C) }, typeof(C)); //get the IL writer for it DynamicILInfo dynamicInfo = dynamicMethod.GetDynamicILInfo(); //set the properties gathered from the compiled expression dynamicMethod.InitLocals = methodState.InitLocals; //set local variables SignatureHelper locals = SignatureHelper.GetLocalVarSigHelper(); foreach (int localIndex in methodState.LocalVariables.Keys) { LocalVariable localVar = methodState.LocalVariables[localIndex]; locals.AddArgument(Type.GetTypeFromHandle(localVar.LocalType), localVar.IsPinned); } dynamicInfo.SetLocalSignature(locals.GetSignature()); //resolve any metadata tokens var tokenResolver = new IlTokenResolver(methodState.TokenOffset.Fields, methodState.TokenOffset.Methods, methodState.TokenOffset.Types, methodState.TokenOffset.LiteralStrings); methodState.CodeBytes = tokenResolver.ResolveCodeTokens(methodState.CodeBytes, dynamicInfo); //set the IL code for the dynamic method dynamicInfo.SetCode(methodState.CodeBytes, methodState.MaxStackSize); //create a delegate for fast execution var expressionDelegate = (ExecuteExpression <R, C>)dynamicMethod.CreateDelegate(typeof(ExecuteExpression <R, C>)); return(expressionDelegate); }
/// <summary> /// Compiles a DynamicMethodState and returns a delegate. /// </summary> /// <typeparam name="R">The return type of the expression</typeparam> /// <typeparam name="C">The type of the function class</typeparam> /// <param name="methodState">The serialized version of a method on the functionClass</param> /// <returns>EvalExpression<R, C> - a delegate that calls the compiled expression</returns> internal EvalExpression <R, C> GetDelegate <R, C>(DynamicMethodState methodState) { ExecuteExpression <R, C> methodDelegate = null; //get delegate factory var delegateFactory = new ExpressionDelegateFactory(); if (methodState != null && methodState.CodeBytes != null) { //get delegate from factory methodDelegate = delegateFactory.CreateExpressionDelegate <R, C>(methodState); } //return an eval delegate based on the delegate from the factory return(new EvalExpression <R, C>(methodDelegate)); }
/// <summary> /// Converts a MethodInfo into a serialized version of it. /// </summary> /// <param name="dynamicMethod">The method for which to create a DynamicMethod for</param> /// <returns>DynamicMethodState - serialized version of a method.</returns> protected DynamicMethodState GetMethodState(MethodInfo dynamicMethod) { var methodState = new DynamicMethodState(); //IL info from method var methodIlCode = dynamicMethod.GetMethodBody(); //get code bytes and other method properties methodState.CodeBytes = methodIlCode.GetILAsByteArray(); methodState.InitLocals = methodIlCode.InitLocals; methodState.MaxStackSize = methodIlCode.MaxStackSize; //get any local variable information IDictionary <int, LocalVariable> locals = new SortedList <int, LocalVariable>(); foreach (var localInfo in methodIlCode.LocalVariables) { locals.Add(localInfo.LocalIndex, new LocalVariable(localInfo.IsPinned, localInfo.LocalType.TypeHandle)); } methodState.LocalVariables = locals; var tokenOffset = new TokenOffset(); //get metadata token offsets var reader = new IlReader(methodState.CodeBytes, dynamicMethod.Module); tokenOffset.Fields = reader.Fields; tokenOffset.Methods = reader.Methods; tokenOffset.Types = reader.Types; tokenOffset.LiteralStrings = reader.LiteralStrings; methodState.TokenOffset = tokenOffset; return(methodState); }