public void ToggleSignal(string iface, string member, Delegate dlg, bool adding) { MatchRule rule = new MatchRule(); rule.MessageType = MessageType.Signal; rule.Interface = iface; rule.Member = member; rule.Path = object_path; if (adding) { if (conn.Handlers.ContainsKey(rule)) { conn.Handlers[rule] = Delegate.Combine(conn.Handlers[rule], dlg); } else { conn.Handlers[rule] = dlg; conn.AddMatch(rule.ToString()); } } else { conn.Handlers[rule] = Delegate.Remove(conn.Handlers[rule], dlg); if (conn.Handlers[rule] == null) { conn.RemoveMatch(rule.ToString()); conn.Handlers.Remove(rule); } } }
public void Invoke(MethodBase methodBase, string methodName, object[] inArgs, out object[] outArgs, out object retVal, out Exception exception) { outArgs = new object[0]; retVal = null; exception = null; MethodInfo mi = methodBase as MethodInfo; if (mi != null && mi.IsSpecialName && (methodName.StartsWith("add_") || methodName.StartsWith("remove_"))) { string[] parts = methodName.Split(new char[] { '_' }, 2); string ename = parts[1]; Delegate dlg = (Delegate)inArgs[0]; MatchRule rule = new MatchRule(); rule.MessageType = MessageType.Signal; rule.Interface = Mapper.GetInterfaceName(mi); rule.Member = ename; rule.Path = object_path; if (parts[0] == "add") { if (conn.Handlers.ContainsKey(rule)) { conn.Handlers[rule] = Delegate.Combine(conn.Handlers[rule], dlg); } else { conn.Handlers[rule] = dlg; conn.AddMatch(rule.ToString()); } } else if (parts[0] == "remove") { conn.Handlers[rule] = Delegate.Remove(conn.Handlers[rule], dlg); if (conn.Handlers[rule] == null) { conn.RemoveMatch(rule.ToString()); conn.Handlers.Remove(rule); } } return; } Type[] inTypes = Mapper.GetTypes(ArgDirection.In, mi.GetParameters()); Signature inSig = Signature.GetSig(inTypes); MethodCall method_call; Message callMsg; //build the outbound method call message { //this bit is error-prone (no null checking) and will need rewriting when DProxy is replaced string iface = null; if (mi != null) { iface = Mapper.GetInterfaceName(mi); } //map property accessors //TODO: this needs to be done properly, not with simple String.Replace //note that IsSpecialName is also for event accessors, but we already handled those and returned if (mi != null && mi.IsSpecialName) { methodName = methodName.Replace("get_", "Get"); methodName = methodName.Replace("set_", "Set"); } method_call = new MethodCall(object_path, iface, methodName, bus_name, inSig); callMsg = method_call.message; if (inArgs != null && inArgs.Length != 0) { MessageWriter writer = new MessageWriter(Connection.NativeEndianness); writer.connection = conn; for (int i = 0; i != inTypes.Length; i++) { writer.Write(inTypes[i], inArgs[i]); } callMsg.Body = writer.ToArray(); } } //TODO: complete out parameter support Type[] outParmTypes = Mapper.GetTypes(ArgDirection.Out, mi.GetParameters()); Signature outParmSig = Signature.GetSig(outParmTypes); if (outParmSig != Signature.Empty) { throw new Exception("Out parameters not yet supported: out_signature='" + outParmSig.Value + "'"); } Type[] outTypes = new Type[1]; outTypes[0] = mi.ReturnType; //we default to always requiring replies for now, even though unnecessary //this is to make sure errors are handled synchronously //TODO: don't hard code this bool needsReply = true; //if (mi.ReturnType == typeof (void)) // needsReply = false; callMsg.ReplyExpected = needsReply; callMsg.Signature = inSig; if (!needsReply) { conn.Send(callMsg); return; } #if PROTO_REPLY_SIGNATURE if (needsReply) { Signature outSig = Signature.GetSig(outTypes); callMsg.Header.Fields[FieldCode.ReplySignature] = outSig; } #endif Message retMsg = conn.SendWithReplyAndBlock(callMsg); //handle the reply message switch (retMsg.Header.MessageType) { case MessageType.MethodReturn: object[] retVals = MessageHelper.GetDynamicValues(retMsg, outTypes); if (retVals.Length != 0) { retVal = retVals[retVals.Length - 1]; } break; case MessageType.Error: //TODO: typed exceptions Error error = new Error(retMsg); string errMsg = String.Empty; if (retMsg.Signature.Value.StartsWith("s")) { MessageReader reader = new MessageReader(retMsg); reader.GetValue(out errMsg); } exception = new Exception(error.ErrorName + ": " + errMsg); break; default: throw new Exception("Got unexpected message of type " + retMsg.Header.MessageType + " while waiting for a MethodReturn or Error"); } return; }