private Emit <Func <int> > EmitConcat(CompilerContext context, Emit <Func <int> > emiter) { ExpressionTyper typer = new ExpressionTyper(); Left.EmitByteCode(context, emiter); if (Left.Whiletype != WhileType.STRING) { var t = TypeConverter.WhileToType(Left.Whiletype); emiter.Box(t); } Right.EmitByteCode(context, emiter); if (Right.Whiletype != WhileType.STRING) { var t = TypeConverter.WhileToType(Right.Whiletype); emiter.Box(t); } var mi = typeof(string).GetMethod("Concat", new[] { typeof(object), typeof(object) }); emiter.Call(mi); return(emiter); }
// ReSharper restore StaticMemberInGenericType private static void SerializeValue(PropertyInfo propInfo, Emit <Action <T, StringBuilder, StringBuilder> > serializationEmitter) { var isString = propInfo.PropertyType == typeof(string); using (var stringLocal = serializationEmitter.DeclareLocal <string>()) { serializationEmitter.LoadConstant(isString ? @"'{0}', " : "{0}, "); serializationEmitter.LoadArgument(0); // instance serializationEmitter.CallVirtual(propInfo.GetGetMethod()); if (isString) { serializationEmitter.Call(stringEscape); serializationEmitter.LoadConstant(Environment.NewLine); serializationEmitter.LoadConstant(@"\n"); serializationEmitter.CallVirtual(stringReplace); } else { serializationEmitter.Box(propInfo.PropertyType); } serializationEmitter.Call(stringFormat); serializationEmitter.StoreLocal(stringLocal); // Append to hotfix builder serializationEmitter.LoadArgument(1); // hotfixBuilder serializationEmitter.LoadLocal(stringLocal); serializationEmitter.Call(stringBuilderAppend); serializationEmitter.Pop(); if (isString) { // Append to locale builder if (localeBuilder != null) var skipLocaleBuilderMark = serializationEmitter.DefineLabel(); serializationEmitter.LoadArgument(2); // instanceBuilder serializationEmitter.LoadNull(); serializationEmitter.CompareEqual(); serializationEmitter.BranchIfTrue(skipLocaleBuilderMark); serializationEmitter.LoadArgument(2); // instanceBuilder serializationEmitter.LoadLocal(stringLocal); serializationEmitter.Call(stringBuilderAppend); serializationEmitter.Pop(); serializationEmitter.MarkLabel(skipLocaleBuilderMark); } } }
/// <summary> /// Creates a simple <see cref="DynamicMethod"/> using <see cref="System.Reflection.Emit"/> that /// calls a method with the specified name and parameter types. /// </summary> /// <param name="type">The <see cref="Type"/> that contains the method to call when the returned delegate is executed..</param> /// <param name="methodName">The name of the method to call when the returned delegate is executed.</param> /// <param name="methodParameterTypes">If not null, use method overload that matches the specified parameters.</param> /// <param name="methodGenericArguments">If not null, use method overload that has the same number of generic arguments.</param> /// <returns>A <see cref="Delegate"/> that can be used to execute the dynamic method.</returns> public static TDelegate CreateMethodCallDelegate( Type type, string methodName, Type[] methodParameterTypes = null, Type[] methodGenericArguments = null) { Type delegateType = typeof(TDelegate); Type[] genericTypeArguments = delegateType.GenericTypeArguments; Type[] parameterTypes; Type returnType; if (delegateType.Name.StartsWith("Func`")) { // last generic type argument is the return type int parameterCount = genericTypeArguments.Length - 1; parameterTypes = new Type[parameterCount]; Array.Copy(genericTypeArguments, parameterTypes, parameterCount); returnType = genericTypeArguments[parameterCount]; } else if (delegateType.Name.StartsWith("Action`")) { parameterTypes = genericTypeArguments; returnType = null; } else { throw new Exception($"Only Func<> or Action<> are supported in {nameof(CreateMethodCallDelegate)}."); } // find any method that matches by name and parameter types IEnumerable <MethodInfo> methods = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static) .Where(m => m.Name == methodName); // if methodParameterTypes was specified, check for a method that matches if (methodParameterTypes != null) { methods = methods.Where( m => { var ps = m.GetParameters(); if (ps.Length != methodParameterTypes.Length) { return(false); } for (var i = 0; i < ps.Length; i++) { var t1 = ps[i].ParameterType; var t2 = methodParameterTypes[i]; // generics can be tricky to compare for type equality // so we will just check the namespace and name if (t1.Namespace != t2.Namespace || t1.Name != t2.Name) { return(false); } } return(true); }); } if (methodGenericArguments != null) { methods = methods.Where( m => m.IsGenericMethodDefinition && m.GetGenericArguments().Length == methodGenericArguments.Length) .ToArray(); } MethodInfo methodInfo = methods.FirstOrDefault(); if (methodInfo == null) { // method not found // TODO: logging return(null); } if (methodGenericArguments != null) { methodInfo = methodInfo.MakeGenericMethod(methodGenericArguments); } Type[] effectiveParameterTypes; IEnumerable <Type> reflectedParameterTypes = methodInfo.GetParameters() .Select(p => p.ParameterType); if (methodInfo.IsStatic) { effectiveParameterTypes = reflectedParameterTypes.ToArray(); } else { // for instance methods, insert object's type as first element in array effectiveParameterTypes = new[] { type } .Concat(reflectedParameterTypes) .ToArray(); } Emit <TDelegate> dynamicMethod = Emit <TDelegate> .NewDynamicMethod(methodInfo.Name); // load each argument and cast or unbox as necessary for (ushort argumentIndex = 0; argumentIndex < parameterTypes.Length; argumentIndex++) { Type delegateParameterType = parameterTypes[argumentIndex]; Type underlyingParameterType = effectiveParameterTypes[argumentIndex]; dynamicMethod.LoadArgument(argumentIndex); if (underlyingParameterType.IsValueType && delegateParameterType == typeof(object)) { dynamicMethod.UnboxAny(underlyingParameterType); } else if (underlyingParameterType != delegateParameterType) { dynamicMethod.CastClass(underlyingParameterType); } } if (methodInfo.IsStatic) { dynamicMethod.Call(methodInfo); } else { // C# compiler always uses CALLVIRT for instance methods // to get the cheap null check, even if they are not virtual dynamicMethod.CallVirtual(methodInfo); } if (methodInfo.ReturnType.IsValueType && returnType == typeof(object)) { dynamicMethod.Box(methodInfo.ReturnType); } else if (methodInfo.ReturnType != returnType) { dynamicMethod.CastClass(returnType); } dynamicMethod.Return(); return(dynamicMethod.CreateDelegate()); }
private static void SerializeValueArray(PropertyInfo propInfo, Emit <Action <T, StringBuilder, StringBuilder> > serializationEmitter) { var loopBodyLabel = serializationEmitter.DefineLabel(); var loopConditionLabel = serializationEmitter.DefineLabel(); var elementType = propInfo.PropertyType.GetElementType(); var isString = elementType == typeof(string); using (var stringLocal = serializationEmitter.DeclareLocal <string>()) using (var iterationLocal = serializationEmitter.DeclareLocal <int>()) { serializationEmitter.LoadConstant(0); serializationEmitter.StoreLocal(iterationLocal); serializationEmitter.Branch(loopConditionLabel); serializationEmitter.MarkLabel(loopBodyLabel); serializationEmitter.LoadConstant(isString ? @"'{0}', " : "{0}, "); serializationEmitter.LoadArgument(0); // instance serializationEmitter.CallVirtual(propInfo.GetGetMethod()); serializationEmitter.LoadLocal(iterationLocal); serializationEmitter.LoadElement(elementType); if (isString) { serializationEmitter.Call(stringEscape); serializationEmitter.LoadConstant(Environment.NewLine); serializationEmitter.LoadConstant(@"\n"); serializationEmitter.CallVirtual(stringReplace); } else { serializationEmitter.Box(elementType); } serializationEmitter.Call(stringFormat); serializationEmitter.StoreLocal(stringLocal); // Append to hotfix builder serializationEmitter.LoadArgument(1); // hotfixBuilder serializationEmitter.LoadLocal(stringLocal); serializationEmitter.Call(stringBuilderAppend); serializationEmitter.Pop(); if (isString) { // Append to locale builder if (localeBuilder != null) var localeBuilderMarker = serializationEmitter.DefineLabel(); serializationEmitter.LoadArgument(2); // instanceBuilder serializationEmitter.LoadNull(); serializationEmitter.CompareEqual(); serializationEmitter.BranchIfTrue(localeBuilderMarker); serializationEmitter.LoadArgument(2); // instanceBuilder serializationEmitter.LoadLocal(stringLocal); serializationEmitter.Call(stringBuilderAppend); serializationEmitter.Pop(); serializationEmitter.MarkLabel(localeBuilderMarker); } serializationEmitter.LoadLocal(iterationLocal); serializationEmitter.LoadConstant(1); serializationEmitter.Add(); serializationEmitter.StoreLocal(iterationLocal); serializationEmitter.MarkLabel(loopConditionLabel); serializationEmitter.LoadLocal(iterationLocal); serializationEmitter.LoadArgument(0); // instance serializationEmitter.CallVirtual(propInfo.GetGetMethod()); serializationEmitter.LoadLength(elementType); serializationEmitter.Convert <int>(); serializationEmitter.CompareLessThan(); serializationEmitter.BranchIfTrue(loopBodyLabel); } }
public void CompileNumeric(NumericNode node) { emit.LoadConstant(node.Value); emit.Box(typeof(double)); }
/// <summary> /// Creates a simple <see cref="DynamicMethod"/> using <see cref="System.Reflection.Emit"/> that /// calls a method with the specified name and parameter types. /// </summary> /// <param name="owningType">The <see cref="Type"/> that contains the method to call when the returned delegate is executed..</param> /// <param name="methodName">The name of the method to call when the returned delegate is executed.</param> /// <param name="returnType">Use method overload that matches the specified return owningType.</param> /// <param name="parameterTypes">If not null, use method overload that matches the specified parameters.</param> /// <param name="genericTypes">If not null, use method overload that has the same number of generic arguments.</param> /// <returns>A <see cref="Delegate"/> that can be used to execute the dynamic method.</returns> public static TDelegate CreateInstrumentedMethodDelegate( Type owningType, string methodName, Type returnType, Type[] parameterTypes, Type[] genericTypes) { if (owningType == null) { throw new ArgumentNullException($"Parameter may not be null: {nameof(owningType)}"); } MethodInfo[] methods = owningType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); MethodInfo candidate = null; Type[] candidateParameterTypes = null; for (ushort i = 0; i < methods.Length; i++) { if (methods[i].Name != methodName) { continue; } if (returnType != null) { if (methods[i].ReturnType != returnType) { continue; } } var candidateGenericTypes = methods[i].GetGenericArguments(); if (candidateGenericTypes.Length != (genericTypes?.Length ?? 0)) { continue; } var candidateParameters = methods[i].GetParameters(); if (candidateParameters.Length != parameterTypes.Length) { continue; } var paramsMatch = true; candidateParameterTypes = new Type[parameterTypes.Length]; for (var t = 0; t < candidateParameters.Length; t++) { var candidateMethodParameterType = candidateParameters[t].ParameterType; var passedInType = parameterTypes[t]; if (!candidateMethodParameterType.IsAssignableFrom(passedInType)) { paramsMatch = false; break; } candidateParameterTypes[t] = candidateMethodParameterType; } if (!paramsMatch) { continue; } candidate = methods[i]; break; } if (candidate == null) { return(null); } if (genericTypes?.Length > 0) { candidate = candidate.MakeGenericMethod(genericTypes); } Type[] methodParameterTypes; var delegateMetadata = DelegateMetadata.Create <TDelegate>(); if (candidate.IsStatic) { methodParameterTypes = candidateParameterTypes; } else { // for instance methods, insert object's owningType as first element in array methodParameterTypes = new[] { owningType } .Concat(candidateParameterTypes) .ToArray(); } Emit <TDelegate> dynamicMethod = Emit <TDelegate> .NewDynamicMethod(candidate.Name); if (methodParameterTypes.Length > 0) { // load each argument and cast or unbox as necessary for (ushort argumentIndex = 0; argumentIndex < methodParameterTypes.Length; argumentIndex++) { Type methodParameterType = methodParameterTypes[argumentIndex]; Type delegateParameterType = delegateMetadata.Parameters[argumentIndex]; dynamicMethod.LoadArgument(argumentIndex); if (methodParameterType.IsValueType && delegateParameterType == typeof(object)) { dynamicMethod.UnboxAny(methodParameterType); } else if (delegateParameterType != methodParameterType) { dynamicMethod.CastClass(methodParameterType); } } } if (candidate.IsStatic) { dynamicMethod.Call(candidate); } else { // C# compiler always uses CALLVIRT for instance methods // to get the cheap null check, even if they are not virtual dynamicMethod.CallVirtual(candidate); } // Non-void return type? if (candidate.ReturnType.IsValueType && delegateMetadata.ReturnType == typeof(object)) { dynamicMethod.Box(candidate.ReturnType); } else if (candidate.ReturnType != delegateMetadata.ReturnType) { dynamicMethod.CastClass(candidate.ReturnType); } dynamicMethod.Return(); return(dynamicMethod.CreateDelegate()); }