Example #1
0
        private (string signature, string code, bool isCompoundValue) buildFromConstructor(string name, Type type, string indent)
        {
            var constructorParameters = type.GetTypeInfo()
                                        .GetConstructors()
                                        .Select(x => x.GetParameters())
                                        .OrderByDescending(x => x.Length)
                                        .First()
            ;
            var builder = new StringBuilder();

            builder.AppendLine(decoder + ".AdvanceToCompoundValue();");
            var signature = "(";

            foreach (var p in constructorParameters)
            {
                var decoderGenerator = new DecoderGenerator(decoder, message);
                decoderGenerator.add(name + "_" + p.Name, p.ParameterType, indent);
                signature += decoderGenerator.Signature;
                builder.Append(decoderGenerator.Result);
            }

            signature += ")";
            builder.Append(indent);
            builder.Append("var " + name + " = new " + Generator.BuildTypeString(type) + "(");
            builder.Append(string.Join(", ", constructorParameters.Select(x => name + "_" + x.Name)));
            builder.Append(");");

            return(signature, builder.ToString(), true);
        }
Example #2
0
        private (string signature, string code, bool isCompoundValue) createMethod(Type type, string name, string indent)
        {
            if (SignatureString.For.ContainsKey(type))
            {
                return(
                    SignatureString.For[type],
                    decoder + ".Get" + type.Name,
                    false
                    );
            }
            else
            {
                var decoderGenerator = new DecoderGenerator(decoder, message);
                decoderGenerator.add(name + "_inner", type, indent + "    ");
                return(
                    decoderGenerator.Signature,
                    @"() =>
" + indent + @"{
" + decoderGenerator.Result + @"
    " + indent + "return " + name + @"_inner;
" + indent + "}",
                    decoderGenerator.IsCompoundValue
                    );
            }
        }
        private static string generateMethodImplementation(MethodInfo methodInfo, string interfaceName)
        {
            if (!methodInfo.Name.EndsWith("Async"))
            {
                throw new InvalidOperationException($"The method '{methodInfo.Name}' does not end with 'Async'");
            }
            var callName = methodInfo.Name.Substring(0, methodInfo.Name.Length - "Async".Length);

            var returnType       = methodInfo.ReturnType;
            var returnTypeString = BuildTypeString(returnType);

            if (returnTypeString != "global::System.Threading.Tasks.Task" &&
                !returnTypeString.StartsWith("global::System.Threading.Tasks.Task<"))
            {
                throw new InvalidOperationException($"The method '{methodInfo.Name}' does not return a Task type");
            }

            var isProperty = propertyName.IsMatch(callName);

            isProperty &= methodInfo.GetCustomAttribute <DbusMethodAttribute>() == null;

            var parameters = methodInfo.GetParameters();

            if (isProperty)
            {
                if (callName.StartsWith("Get"))
                {
                    if (parameters.Length == 0)
                    {
                        isProperty &= true;
                    }
                    else if (parameters[0].ParameterType == typeof(CancellationToken))
                    {
                        isProperty &= true;
                    }
                    else
                    {
                        isProperty = false;
                    }
                }
                else if (callName.StartsWith("Set"))
                {
                    if (parameters.Length == 1 && parameters[0].ParameterType != typeof(CancellationToken))
                    {
                        isProperty &= true;
                    }
                    else if (parameters.Length == 2 && parameters[1].ParameterType == typeof(CancellationToken))
                    {
                        isProperty &= true;
                    }
                    else
                    {
                        isProperty = false;
                    }
                }
            }

            var encoder = new EncoderGenerator("sendBody");
            var cancellationTokenName = "default(global::System.Threading.CancellationToken)";

            if (parameters.Length > 0 || isProperty)
            {
                if (isProperty)
                {
                    encoder.Add($@"""{interfaceName}""", typeof(string));
                    encoder.Add($@"""{callName.Substring(3 /* "Get" or "Set" */)}""", typeof(string));
                    interfaceName = "org.freedesktop.DBus.Properties";
                    callName      = callName.Substring(0, 3); // "Get" or "Set"
                    foreach (var parameter in parameters)
                    {
                        if (parameter.ParameterType == typeof(CancellationToken))
                        {
                            cancellationTokenName = parameter.Name !;
                        }
                        else
                        {
                            encoder.AddVariant(parameter.Name !, parameter.ParameterType);
                        }
                    }
                }
                else
                {
                    foreach (var parameter in parameters)
                    {
                        if (parameter.ParameterType == typeof(CancellationToken))
                        {
                            cancellationTokenName = parameter.Name !;
                        }
                        else
                        {
                            encoder.Add(parameter.Name !, parameter.ParameterType);
                        }
                    }
                }
            }

            string returnStatement;
            var    decoder = new DecoderGenerator("decoder", "receivedMessage");

            if (returnType == typeof(Task))
            {
                returnStatement = "return;";
            }
            else if (isProperty)
            {
                // must be "Get"
                decoder.Add("result", typeof(object), Indent + "    ");
                returnStatement = "return (" + BuildTypeString(returnType.GenericTypeArguments[0]) + ")result;";
            }
            else // Task<T>
            {
                decoder.Add("result", returnType.GenericTypeArguments[0], Indent + "    ");
                returnStatement = "return result;";
            }

            var createFunction = "";

            if (returnType != typeof(Task))
            {
                createFunction = @"
            " + BuildTypeString(methodInfo.ReturnType.GenericTypeArguments[0]) + @" decode(global::Dbus.Decoder decoder)
            {
" + decoder.Result + @"
                " + returnStatement + @"
            }
";
            }

            return(@"
        public async " + returnTypeString + @" " + methodInfo.Name + @"(" + string.Join(", ", methodInfo.GetParameters().Select(x => BuildTypeString(x.ParameterType) + " " + x.Name)) + @")
        {
            var sendBody = new global::Dbus.Encoder();
" + encoder.Result + @"
            var receivedMessage = await connection.SendMethodCall(
                this.path,
                """ + interfaceName + @""",
                """ + callName + @""",
                this.destination,
                sendBody,
                """ + encoder.Signature + @""",
                " + cancellationTokenName + @"
            ).ConfigureAwait(false);
" + (returnType == typeof(Task) ? "" : createFunction) + @"
            using (receivedMessage)
            {
                receivedMessage.AssertSignature(""" + decoder.Signature + @""");
                " + (returnType == typeof(Task) ? "return;" : "return decode(receivedMessage.Decoder);") + @"
            }
        }
");
        }
Example #4
0
        public static (string name, string implementation) GenerateMethodProxy(MethodInfo method)
        {
            if (!method.Name.EndsWith("Async"))
            {
                throw new InvalidOperationException("Only method names ending in 'Async' are supported");
            }
            if (method.ReturnType != typeof(Task) && method.ReturnType.GetGenericTypeDefinition() != typeof(Task <>))
            {
                throw new InvalidOperationException("Only methods returning a Task type are supported");
            }

            var methodName           = method.Name.Substring(0, method.Name.Length - "Async".Length);
            var methodImplementation = new StringBuilder();

            methodImplementation.Append(@"
        private async global::System.Threading.Tasks.Task handle" + method.Name + @"(global::Dbus.MethodCallOptions methodCallOptions, global::Dbus.ReceivedMessage receivedMessage, global::System.Threading.CancellationToken cancellationToken)
        {
");
            var decoder          = new DecoderGenerator("receivedMessage.Decoder", "receivedMessage");
            var methodParameters = new List <string>();

            foreach (var parameter in method.GetParameters())
            {
                if (parameter.ParameterType == typeof(CancellationToken))
                {
                    methodParameters.Add("cancellationToken");
                }
                else
                {
                    decoder.Add(parameter.Name !, parameter.ParameterType);
                    methodParameters.Add(parameter.Name !);
                }
            }

            var encoder = new EncoderGenerator("sendBody");

            if (method.ReturnType != typeof(Task)) // Task<T>
            {
                var returnType = method.ReturnType.GenericTypeArguments[0];
                encoder.Add("methodResult", returnType, Indent);
            }

            methodImplementation.Append(Indent);
            methodImplementation.AppendLine(@"receivedMessage.AssertSignature(""" + decoder.Signature + @""");");
            methodImplementation.Append(decoder.Result);
            methodImplementation.Append(Indent);
            if (encoder.Signature != "")
            {
                methodImplementation.Append("var methodResult = ");
            }
            methodImplementation.Append("await target." + method.Name + "(");
            methodImplementation.Append(string.Join(", ", methodParameters));
            methodImplementation.AppendLine(");");
            methodImplementation.Append(Indent);
            methodImplementation.AppendLine("if (!methodCallOptions.ShouldSendReply)");
            methodImplementation.Append(Indent);
            methodImplementation.AppendLine("    return;");
            methodImplementation.Append(Indent);
            methodImplementation.AppendLine("var sendBody = new global::Dbus.Encoder();");
            if (encoder.Signature != "")
            {
                methodImplementation.Append(encoder.Result);
            }
            methodImplementation.Append(Indent);
            methodImplementation.AppendLine(@"await connection.SendMethodReturnAsync(methodCallOptions, sendBody, """ + encoder.Signature + @""", cancellationToken).ConfigureAwait(false);");
            methodImplementation.Append(@"
        }");

            return(methodName, methodImplementation.ToString());
        }
        public static (string subscription, string implementation) GenerateEventImplementation(EventInfo eventInfo, string interfaceName)
        {
            if (eventInfo.EventHandlerType == null)
            {
                throw new InvalidOperationException("EventInfo has no handler type");
            }

            var subscription = new StringBuilder();

            subscription.Append(Indent);
            subscription.AppendLine("eventSubscriptions.Add(connection.RegisterSignalHandler(");
            subscription.Append(Indent);
            subscription.Append("    ");
            subscription.AppendLine("this.path,");
            subscription.Append(Indent);
            subscription.Append("    ");
            subscription.AppendLine(@"""" + interfaceName + @""",");
            subscription.Append(Indent);
            subscription.Append("    ");
            subscription.AppendLine(@"""" + eventInfo.Name + @""",");
            subscription.Append(Indent);
            subscription.Append("    ");
            subscription.AppendLine("this.handle" + eventInfo.Name);
            subscription.Append(Indent);
            subscription.AppendLine("));");


            var invocationParameters = new List <string>();
            var decoder = new DecoderGenerator("receivedMessage.Decoder", "receivedMessage");

            if (eventInfo.EventHandlerType.IsConstructedGenericType)
            {
                var arguments = eventInfo.EventHandlerType.GenericTypeArguments;
                for (var i = 0; i < arguments.Length; ++i)
                {
                    var invocationParameter = "decoded" + i;
                    decoder.Add(invocationParameter, arguments[i]);
                    invocationParameters.Add(invocationParameter);
                }
            }

            var implementation = new StringBuilder();

            implementation.Append("        ");
            implementation.Append("public event ");
            implementation.Append(BuildTypeString(eventInfo.EventHandlerType));
            implementation.Append(" ");
            implementation.Append(eventInfo.Name);
            implementation.AppendLine(";");
            implementation.Append("        ");
            implementation.Append("private void handle");
            implementation.Append(eventInfo.Name);
            implementation.AppendLine("(global::Dbus.ReceivedMessage receivedMessage)");
            implementation.Append("        ");
            implementation.AppendLine("{");
            implementation.Append(Indent);
            implementation.AppendLine(@"receivedMessage.AssertSignature(""" + decoder.Signature + @""");");
            implementation.Append(decoder.Result);
            implementation.Append(Indent);
            implementation.AppendLine(eventInfo.Name + "?.Invoke(" + string.Join(", ", invocationParameters) + ");");
            implementation.Append("        ");
            implementation.AppendLine("}");

            return(subscription.ToString(), implementation.ToString());
        }