Beispiel #1
0
        private ReactMethodImpl MakeReturningMethod(ReflectionMethodInfo methodInfo, Type returnType, ParameterInfo[] parameters)
        {
            // It is like the MakeCallbackMethod but callback is not passed as a parameter.

            // Input parameters for generated lambda
            ParameterExpression moduleParameter       = Expression.Parameter(typeof(object), "module");
            ParameterExpression inputReaderParameter  = Expression.Parameter(typeof(IJSValueReader), "inputReader");
            ParameterExpression outputWriterParameter = Expression.Parameter(typeof(IJSValueWriter), "outputWriter");
            ParameterExpression resolveParameter      = Expression.Parameter(typeof(MethodResultCallback), "resolve");
            ParameterExpression rejectParameter       = Expression.Parameter(typeof(MethodResultCallback), "reject");

            // Input variables to read from inputReader
            ParameterExpression[] inputVariables = new ParameterExpression[parameters.Length];
            for (int i = 0; i < parameters.Length; ++i)
            {
                inputVariables[i] = Expression.Variable(parameters[i].ParameterType, parameters[i].Name);
            }

            // The result variable to store method call result
            var resultVariable = Expression.Variable(returnType);

            // Statements of the generated lambda
            List <Expression> statements = new List <Expression>();

            // Generate code to read input variables from the inputReader
            var callReadNext = Expression.Call(inputReaderParameter, typeof(IJSValueReader).GetMethod("ReadNext"));

            statements.Add(callReadNext);
            foreach (ParameterExpression variable in inputVariables)
            {
                statements.Add(callReadNext);
                statements.Add(Expression.Call(null, JSValueReader.GetReadValueMethod(variable.Type), inputReaderParameter, variable));
            }

            // Generate code to call the method
            statements.Add(Expression.Assign(resultVariable,
                                             Expression.Call(
                                                 Expression.Convert(moduleParameter, methodInfo.DeclaringType),
                                                 methodInfo,
                                                 inputVariables)));

            // Generate code to write result to outputWriter
            statements.Add(Expression.Call(outputWriterParameter, typeof(IJSValueWriter).GetMethod("WriteArrayBegin")));
            statements.Add(Expression.Call(null, JSValueWriter.GetWriteValueMethod(resultVariable.Type), outputWriterParameter, resultVariable));
            statements.Add(Expression.Call(outputWriterParameter, typeof(IJSValueWriter).GetMethod("WriteArrayEnd")));

            // Generate code to call resolve callback
            statements.Add(Expression.Invoke(resolveParameter, outputWriterParameter));

            // Generate the lambda to return
            var lambda = Expression.Lambda <ReactMethodImpl>(
                Expression.Block(inputVariables.Append(resultVariable), statements),
                moduleParameter, inputReaderParameter, outputWriterParameter, resolveParameter, rejectParameter);

            // Compile and return the lambda
            return(lambda.Compile());
        }
        private ReactConstantImpl MakePropertyConstant(PropertyInfo propertyInfo)
        {
            ParameterExpression moduleParameter = Expression.Parameter(typeof(object), "module");
            ParameterExpression writerParameter = Expression.Parameter(typeof(IJSValueWriter), "writer");

            bool isStatic         = propertyInfo.GetGetMethod().IsStatic;
            Type propertyType     = propertyInfo.PropertyType;
            var  constantProperty = Expression.Property(isStatic ? null : Expression.Convert(moduleParameter, propertyInfo.DeclaringType), propertyInfo);
            var  writeValueCall   = Expression.Call(null, JSValueWriter.GetWriteValueMethod(propertyType), writerParameter, constantProperty);
            var  lambda           = Expression.Lambda <ReactConstantImpl>(writeValueCall, moduleParameter, writerParameter);

            return(lambda.Compile());
        }
        private ReactConstantImpl MakeFieldConstant(FieldInfo fieldInfo)
        {
            ParameterExpression moduleParameter = Expression.Parameter(typeof(object), "module");
            ParameterExpression writerParameter = Expression.Parameter(typeof(IJSValueWriter), "writer");

            bool isStatic       = fieldInfo.IsStatic;
            Type fieldType      = fieldInfo.FieldType;
            var  constantField  = Expression.Field(isStatic ? null : Expression.Convert(moduleParameter, fieldInfo.DeclaringType), fieldInfo);
            var  writeValueCall = Expression.Call(null, JSValueWriter.GetWriteValueMethod(fieldType), writerParameter, constantField);
            var  lambda         = Expression.Lambda <ReactConstantImpl>(writeValueCall, moduleParameter, writerParameter);

            return(lambda.Compile());
        }
        private ReactEventImpl MakeEvent(PropertyInfo propertyInfo, ParameterInfo parameter)
        {
            // We need to create a delegate that can assign correct delegate to the event property.
            // This is the shape of the generated code:
            //
            //(object module, RaiseEvent raiseEvent) =>
            //{
            //  ((MyModule)module).eventProperty = (ArgType arg) =>
            //  {
            //    raiseEvent((IJSValueWriter argWriter) => WriteValue(argWriter, arg));
            //  };
            //});
            //

            // Input parameters for generated lambda
            ParameterExpression moduleParameter     = Expression.Parameter(typeof(object), "module");
            ParameterExpression raiseEventParameter = Expression.Parameter(typeof(ReactEventHandler), "eventHandler");

            // Create a lambda to be passed to raiseEvent
            ParameterExpression argParameter       = Expression.Parameter(parameter.ParameterType, "arg");
            ParameterExpression argWriterParameter = Expression.Parameter(typeof(IJSValueWriter), "argWriter");
            var writeValueCall     = Expression.Call(null, JSValueWriter.GetWriteValueMethod(parameter.ParameterType), argWriterParameter, argParameter);
            var eventHandlerLambda = Expression.Lambda <ReactArgWriter>(writeValueCall, argWriterParameter);

            // Create a lambda that we assign to the event property
            var raiseEventCall = Expression.Invoke(raiseEventParameter, eventHandlerLambda);
            var eventLambda    = Expression.Lambda(propertyInfo.PropertyType, raiseEventCall, argParameter);

            // Create lambda that we return and which assigns the event property
            var eventProperty           = Expression.Property(Expression.Convert(moduleParameter, propertyInfo.DeclaringType), propertyInfo);
            var eventPropertyAssignment = Expression.Assign(eventProperty, eventLambda);
            var lambda = Expression.Lambda <ReactEventImpl>(eventPropertyAssignment, moduleParameter, raiseEventParameter);

            // Compile and return the lambda
            return(lambda.Compile());
        }
Beispiel #5
0
        private ReactMethodImpl MakeCallbackMethod(ReflectionMethodInfo methodInfo, ParameterInfo[] parameters)
        {
            // The last variable is a delegate

            // Input parameters for generated lambda
            ParameterExpression moduleParameter       = Expression.Parameter(typeof(object), "module");
            ParameterExpression inputReaderParameter  = Expression.Parameter(typeof(IJSValueReader), "inputReader");
            ParameterExpression outputWriterParameter = Expression.Parameter(typeof(IJSValueWriter), "outputWriter");
            ParameterExpression resolveParameter      = Expression.Parameter(typeof(MethodResultCallback), "resolve");
            ParameterExpression rejectParameter       = Expression.Parameter(typeof(MethodResultCallback), "reject");

            // Input variables to read from inputReader
            ParameterExpression[] inputVariables = new ParameterExpression[parameters.Length - 1];
            for (int i = 0; i < inputVariables.Length; ++i)
            {
                inputVariables[i] = Expression.Variable(parameters[i].ParameterType, parameters[i].Name);
            }

            // Generate the resolve delegate
            var inputResolveParameter = parameters[parameters.Length - 1];
            var resolveMethodInfo     = inputResolveParameter.ParameterType.GetMethod("Invoke");

            ParameterInfo[] resolveMethodParameters = resolveMethodInfo.GetParameters();
            if (resolveMethodParameters.Length != 1)
            {
                throw new ArgumentException($"Resolve callback type must have one parameter. Method: {MethodName}, Parameter: {inputResolveParameter.Name}");
            }
            Type resolveParameterType = resolveMethodParameters[0].ParameterType;
            ParameterExpression resolveLambdaParameter = Expression.Parameter(resolveParameterType, "value");

            List <Expression> resolveStatements = new List <Expression>();

            resolveStatements.Add(Expression.Call(outputWriterParameter, typeof(IJSValueWriter).GetMethod("WriteArrayBegin")));
            resolveStatements.Add(Expression.Call(null, JSValueWriter.GetWriteValueMethod(resolveParameterType), outputWriterParameter, resolveLambdaParameter));
            resolveStatements.Add(Expression.Call(outputWriterParameter, typeof(IJSValueWriter).GetMethod("WriteArrayEnd")));
            resolveStatements.Add(Expression.Invoke(resolveParameter, outputWriterParameter));
            var resolveLambda = Expression.Lambda(inputResolveParameter.ParameterType, Expression.Block(resolveStatements), resolveLambdaParameter);

            // Statements of the generated lambda
            List <Expression> statements = new List <Expression>();

            // Generate code to read input variables from the inputReader
            var callReadNext = Expression.Call(inputReaderParameter, typeof(IJSValueReader).GetMethod("ReadNext"));

            statements.Add(callReadNext);
            foreach (ParameterExpression variable in inputVariables)
            {
                statements.Add(callReadNext);
                statements.Add(Expression.Call(null, JSValueReader.GetReadValueMethod(variable.Type), inputReaderParameter, variable));
            }

            // Generate code to call the method
            statements.Add(Expression.Call(
                               Expression.Convert(moduleParameter, methodInfo.DeclaringType),
                               methodInfo,
                               (inputVariables as IEnumerable <Expression>).Append(resolveLambda)));

            // Generate the lambda to return
            var lambda = Expression.Lambda <ReactMethodImpl>(
                Expression.Block(inputVariables, statements),
                moduleParameter, inputReaderParameter, outputWriterParameter, resolveParameter, rejectParameter);

            // Compile and return the lambda
            return(lambda.Compile());
        }