Beispiel #1
0
        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);
                }
            }
        }
Beispiel #3
0
        /// <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);
                }
        }
Beispiel #5
0
 public void CompileNumeric(NumericNode node)
 {
     emit.LoadConstant(node.Value);
     emit.Box(typeof(double));
 }
Beispiel #6
0
        /// <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());
        }