Ejemplo n.º 1
0
        /// <summary>
        /// Dynamically resolves and executes a method call serialized with
        /// our Protobuf-based RPC scheme
        /// </summary>
        public static RPCFuncReturnVal DoMethodCall <TIface>(
            RPCFuncCall call, TIface impl,
            ProtoBufByteConverter byteConverter,
            TypeModel customSerializer)
        {
            if (call == null)
            {
                return(RPCFuncReturnVal.BuildRPCError("Server received empty RPC message"));
            }
            if (impl == null)
            {
                throw new ArgumentNullException("impl");
            }
            if (byteConverter == null)
            {
                throw new ArgumentNullException("byteConverter");
            }

            var methods = Utilities.RecurseInterfaces(typeof(TIface), t => t.GetMethods()).Where(m => m.Name == call.FuncName).Distinct().ToArray();

            if (methods.Length < 1)
            {
                return(RPCFuncReturnVal.BuildRPCError("RPC Function name not found " + call.FuncName));
            }
            else if (methods.Length > 1)
            {
                return(RPCFuncReturnVal.BuildRPCError("More than one method found with name " + call.FuncName));
            }

            var method = methods[0];

            if (method == null)
            {
                return(RPCFuncReturnVal.BuildRPCError("RPC Function name not found " + call.FuncName));
            }
            var args = call.Args;

            if (args == null)
            {
                args = new RPCFuncArgVal[0];
            }
            var mParameters = method.GetParameters();

            if (mParameters.Length != args.Length)
            {
                return(RPCFuncReturnVal.BuildRPCError(
                           string.Format("RPC argument list for function {0} should have {1} elements, but was passed {1}",
                                         call.FuncName, mParameters.Length, args.Length)));
            }

            MemoryStream ms = new MemoryStream();

            object[] parameters = new object[mParameters.Length];
            for (int i = 0; i < args.Length; i++)
            {
                var a = args[i];
                var p = mParameters[i];

                if (a.ArgDef != null)
                {
                    if ((a.ArgDef.Name != p.Name) || (a.ArgDef.Type != p.ParameterType.Name))
                    {
                        return(RPCFuncReturnVal.BuildRPCError(string.Format(
                                                                  "RPC argument metadata was specified (is optional) and "
                                                                  + "didn't match expected values: arg #{0} expected ({1} {2}) but given ({3} {4})",
                                                                  i, p.ParameterType.Name, p.Name, a.ArgDef.Type, a.ArgDef.Name)));
                    }
                }
                try
                {
                    parameters[i] = byteConverter.FromBytes(a.ArgValue, p.ParameterType);
                }
                catch (Exception e)
                {
                    return(RPCFuncReturnVal.BuildRPCError(string.Format(
                                                              "Unable to deserialize argument #{0}: {1} {2} (given {3} bytes): {4}",
                                                              i, p.ParameterType.Name, p.Name, a.ArgValue.Length, e.ToString())));
                }
            }

            object retVal = null;

            try { retVal = method.Invoke(impl, parameters); }
            catch (Exception e)
            {
                return(RPCFuncReturnVal.BuildFuncExceptionError(e.ToString()));
            }
            byte[] retValBytes = (retVal == null) ? new byte[0] : byteConverter.ToBytes(retVal);
            return(RPCFuncReturnVal.BuildOK(retValBytes));
        }
 public void Setup_ProtoBufByteConverter()
 {
     Converter  = new ProtoBufByteConverter <string>();
     TestString = GetTestString();
 }
 public void Setup_ProtoBufByteConverter()
 {
     Converter = new ProtoBufByteConverter <ComplexType>();
     Input     = CreateComplexType();
 }