Beispiel #1
0
        public void EmitAsynchronousHandlers(ArrayList asynchronousHandlers)
        {
            EmitLine("    public override bool DispatchAsynchronous(RabbitMQ.Client.Impl.Command cmd) {");
            EmitLine("      RabbitMQ.Client.Impl.MethodBase __method = (RabbitMQ.Client.Impl.MethodBase) cmd.Method;");
            EmitLine("      switch ((__method.ProtocolClassId << 16) | __method.ProtocolMethodId) {");
            foreach (MethodInfo method in asynchronousHandlers)
            {
                string methodName = method.Name;
                if (methodName.StartsWith("Handle"))
                {
                    methodName = methodName.Substring(6);
                }

                AmqpClass  amqpClass  = null;
                AmqpMethod amqpMethod = null;
                LookupAmqpMethod(method, methodName, out amqpClass, out amqpMethod);

                string implClass = MangleMethodClass(amqpClass, amqpMethod);

                EmitLine("        case " + ((amqpClass.Index << 16) | amqpMethod.Index) + ": {");
                ParameterInfo[] parameters = method.GetParameters();
                if (parameters.Length > 0)
                {
                    EmitLine("          " + implClass + " __impl = (" + implClass + ") __method;");
                    EmitLine("          " + method.Name + "(");
                    int remaining = parameters.Length;
                    foreach (ParameterInfo pi in parameters)
                    {
                        if (Attribute(pi, typeof(AmqpContentHeaderMappingAttribute)) != null)
                        {
                            Emit("            (" + pi.ParameterType + ") cmd.Header");
                        }
                        else if (Attribute(pi, typeof(AmqpContentBodyMappingAttribute)) != null)
                        {
                            Emit("            cmd.Body");
                        }
                        else
                        {
                            AmqpFieldMappingAttribute fieldMapping =
                                Attribute(pi, typeof(AmqpFieldMappingAttribute)) as AmqpFieldMappingAttribute;
                            Emit("            __impl.m_" + (fieldMapping == null
                                                          ? pi.Name
                                                          : fieldMapping.m_fieldName));
                        }
                        remaining--;
                        if (remaining > 0)
                        {
                            EmitLine(",");
                        }
                    }
                    EmitLine(");");
                }
                else
                {
                    EmitLine("          " + method.Name + "();");
                }
                EmitLine("          return true;");
                EmitLine("        }");
            }
            EmitLine("        default: return false;");
            EmitLine("      }");
            EmitLine("    }");
        }
Beispiel #2
0
        public void EmitModelMethod(MethodInfo method)
        {
            ParameterInfo[] parameters = method.GetParameters();

            AmqpClass  amqpClass  = null;
            AmqpMethod amqpMethod = null;

            LookupAmqpMethod(method, method.Name, out amqpClass, out amqpMethod);

            string requestImplClass = MangleMethodClass(amqpClass, amqpMethod);

            // At this point, we know which request method to
            // send. Now compute whether it's an RPC or not.

            AmqpMethod amqpReplyMethod = null;
            AmqpMethodMappingAttribute replyMapping =
                Attribute(method.ReturnTypeCustomAttributes, typeof(AmqpMethodMappingAttribute))
                as AmqpMethodMappingAttribute;

            if (Attribute(method, typeof(AmqpForceOneWayAttribute)) == null &&
                (amqpMethod.IsSimpleRpcRequest || replyMapping != null))
            {
                // We're not forcing oneway, and either are a simple
                // RPC request, or have an explicit replyMapping
                amqpReplyMethod = amqpClass.MethodNamed(replyMapping == null
                                                        ? (string)amqpMethod.m_ResponseMethods[0]
                                                        : replyMapping.m_methodName);
                if (amqpReplyMethod == null)
                {
                    throw new Exception("Could not find AMQP reply method for IModel method " + method.Name);
                }
            }

            // If amqpReplyMethod is null at this point, it's a
            // one-way operation, and no continuation needs to be
            // consed up. Otherwise, we should expect a reply of kind
            // identified by amqpReplyMethod - unless there's a nowait
            // parameter thrown into the equation!
            //
            // Examine the parameters to discover which might be
            // nowait, content header or content body.

            ParameterInfo nowaitParameter        = null;
            string        nowaitExpression       = "null";
            ParameterInfo contentHeaderParameter = null;
            ParameterInfo contentBodyParameter   = null;

            foreach (ParameterInfo pi in parameters)
            {
                AmqpNowaitArgumentAttribute nwAttr =
                    Attribute(pi, typeof(AmqpNowaitArgumentAttribute)) as AmqpNowaitArgumentAttribute;
                if (nwAttr != null)
                {
                    nowaitParameter = pi;
                    if (nwAttr.m_replacementExpression != null)
                    {
                        nowaitExpression = nwAttr.m_replacementExpression;
                    }
                }
                if (Attribute(pi, typeof(AmqpContentHeaderMappingAttribute)) != null)
                {
                    contentHeaderParameter = pi;
                }
                if (Attribute(pi, typeof(AmqpContentBodyMappingAttribute)) != null)
                {
                    contentBodyParameter = pi;
                }
            }

            // Compute expression text for the content header and body.

            string contentHeaderExpr =
                contentHeaderParameter == null
                ? "null"
                : " (" + MangleClass(amqpClass.Name) + "Properties) " + contentHeaderParameter.Name;
            string contentBodyExpr =
                contentBodyParameter == null ? "null" : contentBodyParameter.Name;

            // Emit the method declaration and preamble.

            EmitModelMethodPreamble(method);
            EmitLine("    {");

            // Emit the code to build the request.

            EmitLine("      " + requestImplClass + " __req = new " + requestImplClass + "();");
            foreach (ParameterInfo pi in parameters)
            {
                if (pi != contentHeaderParameter &&
                    pi != contentBodyParameter)
                {
                    if (Attribute(pi, typeof(AmqpUnsupportedAttribute)) != null)
                    {
                        EmitLine("      if (@" + pi.Name + " != null) {");
                        EmitLine("        throw new UnsupportedMethodFieldException(\"" + method.Name + "\",\"" + pi.Name + "\");");
                        EmitLine("      }");
                    }
                    else
                    {
                        AmqpFieldMappingAttribute fieldMapping =
                            Attribute(pi, typeof(AmqpFieldMappingAttribute)) as AmqpFieldMappingAttribute;
                        if (fieldMapping != null)
                        {
                            EmitLine("      __req.m_" + fieldMapping.m_fieldName + " = @" + pi.Name + ";");
                        }
                        else
                        {
                            EmitLine("      __req.m_" + pi.Name + " = @" + pi.Name + ";");
                        }
                    }
                }
            }

            // If we have a nowait parameter, sometimes that can turn
            // a ModelRpc call into a ModelSend call.

            if (nowaitParameter != null)
            {
                EmitLine("      if (" + nowaitParameter.Name + ") {");
                EmitLine("        ModelSend(__req," + contentHeaderExpr + "," + contentBodyExpr + ");");
                if (method.ReturnType != typeof(void))
                {
                    EmitLine("        return " + nowaitExpression + ";");
                }
                EmitLine("      }");
            }

            // At this point, perform either a ModelRpc or a
            // ModelSend.

            if (amqpReplyMethod == null)
            {
                EmitLine("      ModelSend(__req," + contentHeaderExpr + "," + contentBodyExpr + ");");
            }
            else
            {
                string replyImplClass = MangleMethodClass(amqpClass, amqpReplyMethod);

                EmitLine("      RabbitMQ.Client.Impl.MethodBase __repBase = ModelRpc(__req," + contentHeaderExpr + "," + contentBodyExpr + ");");
                EmitLine("      " + replyImplClass + " __rep = __repBase as " + replyImplClass + ";");
                EmitLine("      if (__rep == null) throw new UnexpectedMethodException(__repBase);");

                if (method.ReturnType == typeof(void))
                {
                    // No need to further examine the reply.
                }
                else
                {
                    // At this point, we have the reply method. Extract values from it.
                    AmqpFieldMappingAttribute returnMapping =
                        Attribute(method.ReturnTypeCustomAttributes, typeof(AmqpFieldMappingAttribute))
                        as AmqpFieldMappingAttribute;
                    if (returnMapping == null)
                    {
                        string fieldPrefix = IsAmqpClass(method.ReturnType) ? "m_" : "";

                        // No field mapping --> it's assumed to be a struct to fill in.
                        EmitLine("      " + method.ReturnType + " __result = new " + method.ReturnType + "();");
                        foreach (FieldInfo fi in method.ReturnType.GetFields())
                        {
                            AmqpFieldMappingAttribute returnFieldMapping =
                                Attribute(fi, typeof(AmqpFieldMappingAttribute)) as AmqpFieldMappingAttribute;
                            if (returnFieldMapping != null)
                            {
                                EmitLine("      __result." + fi.Name + " = __rep." + fieldPrefix + returnFieldMapping.m_fieldName + ";");
                            }
                            else
                            {
                                EmitLine("      __result." + fi.Name + " = __rep." + fieldPrefix + fi.Name + ";");
                            }
                        }
                        EmitLine("      return __result;");
                    }
                    else
                    {
                        // Field mapping --> return just the field we're interested in.
                        EmitLine("      return __rep.m_" + returnMapping.m_fieldName + ";");
                    }
                }
            }

            // All the IO and result-extraction has been done. Emit
            // the method postamble.

            EmitLine("    }");
        }