public void LookupAmqpMethod(MethodInfo method, string methodName, out AmqpClass amqpClass, out AmqpMethod amqpMethod) { amqpClass = null; amqpMethod = null; // First, try autodetecting the class/method via the // IModel method name. foreach (AmqpClass c in m_classes) { foreach (AmqpMethod m in c.m_Methods) { if (methodName.Equals(MangleMethodClass(c, m))) { amqpClass = c; amqpMethod = m; goto stopSearching; // wheee } } } stopSearching: // If an explicit mapping was provided as an attribute, // then use that instead, whether the autodetect worked or // not. { AmqpMethodMappingAttribute methodMapping = Attribute(method, typeof(AmqpMethodMappingAttribute)) as AmqpMethodMappingAttribute; if (methodMapping != null) { amqpClass = null; foreach (AmqpClass c in m_classes) { if (c.Name == methodMapping.m_className) { amqpClass = c; break; } } amqpMethod = amqpClass.MethodNamed(methodMapping.m_methodName); } } // At this point, if can't find either the class or the // method, we can't proceed. Complain. if (amqpClass == null || amqpMethod == null) { throw new Exception("Could not find AMQP class or method for IModel method " + method.Name); } }
public void LookupAmqpMethod(MethodInfo method, string methodName, out AmqpClass amqpClass, out AmqpMethod amqpMethod) { amqpClass = null; amqpMethod = null; // First, try autodetecting the class/method via the // IModel method name. foreach (AmqpClass c in m_classes) { foreach (AmqpMethod m in c.m_Methods) { if (methodName.Equals(MangleMethodClass(c,m))) { amqpClass = c; amqpMethod = m; goto stopSearching; // wheee } } } stopSearching: // If an explicit mapping was provided as an attribute, // then use that instead, whether the autodetect worked or // not. { AmqpMethodMappingAttribute methodMapping = Attribute(method, typeof(AmqpMethodMappingAttribute)) as AmqpMethodMappingAttribute; if (methodMapping != null) { amqpClass = null; foreach (AmqpClass c in m_classes) { if (c.Name == methodMapping.m_className) { amqpClass = c; break; } } amqpMethod = amqpClass.MethodNamed(methodMapping.m_methodName); } } // At this point, if can't find either the class or the // method, we can't proceed. Complain. if (amqpClass == null || amqpMethod == null) { throw new Exception("Could not find AMQP class or method for IModel method " + method.Name); } }
public static string MangleMethodClass(AmqpClass c, AmqpMethod m) { return MangleClass(c.Name) + MangleClass(m.Name); }
public static string MangleMethodClass(AmqpClass c, AmqpMethod m) { return(MangleClass(c.Name) + MangleClass(m.Name)); }
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(" }"); }
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(" }"); }