Ejemplo n.º 1
0
        /// <summary>
        /// Writes the specified method call on the specified protocol.
        /// </summary>
        public static void Write(ThriftMethod method, object[] args, IThriftProtocol protocol)
        {
            if (!_knownWriters.ContainsKey(method))
            {
                _knownWriters.TryAdd(method, CreateWriterForMethod(method).Compile());
            }

            _knownWriters[method](args, protocol);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Reads a ThriftMessage returned by the specified method on the specified protocol.
        /// </summary>
        public static T Read <T>(ThriftMethod method, IThriftProtocol protocol)
        {
            if (!_knownReaders.ContainsKey(method))
            {
                _knownReaders.TryAdd(method, CreateReaderForMethod(method).Compile());
            }

            return(((Func <IThriftProtocol, T>)_knownReaders[method])(protocol));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Creates a writer for the specified method.
        /// </summary>
        private static Expression <Action <object[], IThriftProtocol> > CreateWriterForMethod(ThriftMethod method)
        {
            var argsParam     = Expression.Parameter(typeof(object[]));
            var protocolParam = Expression.Parameter(typeof(IThriftProtocol));

            var methodContents = new List <Expression>
            {
                Expression.Call(
                    protocolParam,
                    Methods.IThriftProtocol_WriteMessageHeader,
                    Expression.New(
                        Constructors.ThriftMessageHeader,
                        Expression.Constant(method.Name),
                        Expression.Constant(method.IsOneWay ? ThriftMessageType.OneWay : ThriftMessageType.Call)
                        )
                    ),

                Expression.Call(
                    protocolParam,
                    Methods.IThriftProtocol_WriteStructHeader,
                    Expression.New(
                        Constructors.ThriftStructHeader,
                        Expression.Constant("")
                        )
                    )
            };

            for (int n = 0; n < method.Parameters.Count; n++)
            {
                var wireField = ThriftWireField.Parameter(method.Parameters[n], argsParam, n);
                methodContents.Add(ThriftStructWriter.CreateWriterForField(protocolParam, wireField));
            }

            methodContents.Add(Expression.Call(protocolParam, Methods.IThriftProtocol_WriteFieldStop));
            methodContents.Add(Expression.Call(protocolParam, Methods.IThriftProtocol_WriteStructEnd));
            methodContents.Add(Expression.Call(protocolParam, Methods.IThriftProtocol_WriteMessageEnd));

            return(Expression.Lambda <Action <object[], IThriftProtocol> >(
                       Expression.Block(methodContents),
                       argsParam, protocolParam
                       ));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Creates a reader for the specified method.
        /// </summary>
        private static LambdaExpression CreateReaderForMethod(ThriftMethod method)
        {
            var protocolParam = Expression.Parameter(typeof(IThriftProtocol));

            var headerVariable = Expression.Variable(typeof(ThriftMessageHeader));
            ParameterExpression hasReturnVariable = null;
            ParameterExpression returnVariable    = null;

            if (method.ReturnValue.UnderlyingTypeInfo != TypeInfos.Void)
            {
                hasReturnVariable = Expression.Variable(typeof(bool));
                returnVariable    = Expression.Variable(method.ReturnValue.UnderlyingTypeInfo.AsType());
            }

            var wireFields = new List <ThriftWireField>();

            if (returnVariable != null)
            {
                wireFields.Add(ThriftWireField.ReturnValue(method.ReturnValue, returnVariable, hasReturnVariable));
            }
            foreach (var exception in method.Exceptions)
            {
                wireFields.Add(ThriftWireField.ThrowsClause(exception));
            }

            var statements = new List <Expression>
            {
                Expression.Assign(
                    headerVariable,
                    Expression.Call(
                        protocolParam,
                        Methods.IThriftProtocol_ReadMessageHeader
                        )
                    ),

                Expression.IfThen(
                    // Do not use IsFalse, not supported by UWP's expression interpreter
                    Expression.Equal(
                        Expression.Call(
                            Methods.Enum_IsDefined,
                            // The second argument is absolutely crucial here.
                            // System.Type is an abstract class, implemented by an internal framework class System.RuntimeType
                            // Not specifying the argument leads to the expression's type being typeof(System.RuntimeType),
                            // which crashes on frameworks that restrict access to non-public framework types, such as Windows Phone 8.1
                            Expression.Constant(typeof(ThriftMessageType), typeof(Type)),
                            Expression.Convert(
                                Expression.Field(headerVariable, Fields.ThriftMessageHeader_MessageType),
                                typeof(object)
                                )
                            ),
                        Expression.Constant(false)
                        ),
                    Expression.Throw(
                        Expression.New(
                            Constructors.ThriftProtocolException,
                            Expression.Constant(ThriftProtocolExceptionType.InvalidMessageType)
                            )
                        )
                    ),

                Expression.IfThen(
                    Expression.Equal(
                        Expression.Field(headerVariable, Fields.ThriftMessageHeader_MessageType),
                        Expression.Constant(ThriftMessageType.Exception)
                        ),
                    Expression.Throw(
                        Expression.Call(
                            typeof(ThriftStructReader),
                            "Read",
                            new[] { typeof(ThriftProtocolException) },
                            protocolParam
                            )
                        )
                    ),

                ThriftStructReader.CreateReaderForFields(protocolParam, wireFields),

                Expression.Call(protocolParam, Methods.IThriftProtocol_ReadMessageEnd)
            };

            if (returnVariable != null)
            {
                statements.Add(
                    Expression.IfThen(
                        Expression.Equal(
                            hasReturnVariable,
                            Expression.Constant(false)
                            ),
                        Expression.Throw(
                            Expression.New(
                                Constructors.ThriftProtocolException,
                                Expression.Constant(ThriftProtocolExceptionType.MissingResult)
                                )
                            )
                        )
                    );
            }

            if (returnVariable == null)
            {
                statements.Add(Expression.Constant(null));
            }
            else
            {
                statements.Add(returnVariable);
            }

            return(Expression.Lambda(
                       Expression.Block(
                           returnVariable?.Type ?? typeof(object),
                           returnVariable == null ? new[] { headerVariable } : new[] { headerVariable, hasReturnVariable, returnVariable },
                           statements
                           ),
                       new[] { protocolParam }
                       ));
        }