private MethodInfo GenSendSignal(SignalDescription signalDescription, bool isPropertiesChangedSignal) { var key = $"{signalDescription.Interface.Name}.{signalDescription.Name}"; var method = _typeBuilder.DefineMethod($"Emit{key}".Replace('.', '_'), MethodAttributes.Private, null, signalDescription.SignalType == null ? Type.EmptyTypes : new[] { signalDescription.SignalType }); var ilg = method.GetILGenerator(); ilg.Emit(OpCodes.Ldarg_0); if (isPropertiesChangedSignal) { ilg.Emit(OpCodes.Ldstr, "org.freedesktop.DBus.Properties"); ilg.Emit(OpCodes.Ldstr, "PropertiesChanged"); } else { ilg.Emit(OpCodes.Ldstr, signalDescription.Interface.Name); ilg.Emit(OpCodes.Ldstr, signalDescription.Name); } if (signalDescription.SignalType == null) { ilg.Emit(OpCodes.Call, s_emitVoidSignal); } else { // Signature if (isPropertiesChangedSignal) { ilg.Emit(OpCodes.Ldstr, "sa{sv}as"); ilg.Emit(OpCodes.Newobj, s_signatureConstructor); ilg.Emit(OpCodes.Newobj, s_nullableSignatureConstructor); } else if (signalDescription.SignalSignature.HasValue) { ilg.Emit(OpCodes.Ldstr, signalDescription.SignalSignature.Value.Value); ilg.Emit(OpCodes.Newobj, s_signatureConstructor); ilg.Emit(OpCodes.Newobj, s_nullableSignatureConstructor); } else { LocalBuilder signature = ilg.DeclareLocal(s_nullableSignatureType); ilg.Emit(OpCodes.Ldloca_S, signature); ilg.Emit(OpCodes.Initobj, s_nullableSignatureType); ilg.Emit(OpCodes.Ldloc, signature); } // Writer ilg.Emit(OpCodes.Newobj, s_messageWriterConstructor); if (isPropertiesChangedSignal) { ilg.Emit(OpCodes.Dup); ilg.Emit(OpCodes.Ldstr, signalDescription.Interface.Name); ilg.Emit(OpCodes.Call, s_writerWriteString); ilg.Emit(OpCodes.Dup); ilg.Emit(OpCodes.Call, s_writerSetSkipNextStructPadding); } ilg.Emit(OpCodes.Dup); ilg.Emit(OpCodes.Ldarg_1); ilg.Emit(OpCodes.Call, WriteMethodFactory.CreateWriteMethodForType(signalDescription.SignalType, isCompileTimeType: true)); ilg.Emit(OpCodes.Call, s_emitNonVoidSignal); } ilg.Emit(OpCodes.Ret); return(method); }
private MethodInfo GenMethodHandler(string key, MethodDescription dbusMethod, bool propertyMethod) { // Task<Message> MethodCall(object o(Ldarg_1), Message methodCall(Ldarg_2), IProxyFactory(Ldarg_3)); string methodName = $"Handle{key}".Replace('.', '_'); var method = _typeBuilder.DefineMethod(methodName, MethodAttributes.Private, s_taskOfMessageType, s_methodHandlerParameterTypes); var ilg = method.GetILGenerator(); // call CreateReply // this ilg.Emit(OpCodes.Ldarg_0); // Message ilg.Emit(OpCodes.Ldarg_2); // Task = (IDbusInterface)object.CallMethod(arguments) { // (IIinterface)object ilg.Emit(OpCodes.Ldarg_1); ilg.Emit(OpCodes.Castclass, dbusMethod.Interface.Type); // Arguments if (dbusMethod.InArguments.Count != 0) { // create reader for reading the arguments ilg.Emit(OpCodes.Ldarg_2); // message ilg.Emit(OpCodes.Ldarg_3); // IProxyFactory LocalBuilder reader = ilg.DeclareLocal(s_messageReaderType); ilg.Emit(OpCodes.Newobj, s_messageReaderConstructor); // new MessageReader(message, proxyFactory) ilg.Emit(OpCodes.Stloc, reader); if (propertyMethod) { ilg.Emit(OpCodes.Ldloc, reader); ilg.Emit(OpCodes.Call, s_readerSkipString); } foreach (var argument in dbusMethod.InArguments) { Type parameterType = argument.Type; ilg.Emit(OpCodes.Ldloc, reader); ilg.Emit(OpCodes.Call, ReadMethodFactory.CreateReadMethodForType(parameterType)); } } // Call method ilg.Emit(OpCodes.Callvirt, dbusMethod.MethodInfo); } if (dbusMethod.OutType != null) { // Action<MessageWriter, T> ilg.Emit(OpCodes.Ldnull); ilg.Emit(OpCodes.Ldftn, WriteMethodFactory.CreateWriteMethodForType(dbusMethod.OutType, isCompileTimeType: true)); var actionConstructor = s_action2GenericType.MakeGenericType(new[] { s_messageWriterType, dbusMethod.OutType }).GetConstructors()[0]; ilg.Emit(OpCodes.Newobj, actionConstructor); // signature if (dbusMethod.OutSignature.HasValue) { ilg.Emit(OpCodes.Ldstr, dbusMethod.OutSignature.Value.Value); ilg.Emit(OpCodes.Newobj, s_signatureConstructor); ilg.Emit(OpCodes.Newobj, s_nullableSignatureConstructor); } else { LocalBuilder signature = ilg.DeclareLocal(s_nullableSignatureType); ilg.Emit(OpCodes.Ldloca_S, signature); ilg.Emit(OpCodes.Initobj, s_nullableSignatureType); ilg.Emit(OpCodes.Ldloc, signature); } // CreateReply ilg.Emit(OpCodes.Call, s_createNonVoidReply.MakeGenericMethod(new[] { dbusMethod.OutType })); } else { // CreateReply ilg.Emit(OpCodes.Call, s_createVoidReply); } ilg.Emit(OpCodes.Ret); return(method); }
private void ImplementMethod(MethodDescription methodDescription, bool propertyMethod) { var method = _typeBuilder.ImplementInterfaceMethod(methodDescription.MethodInfo); ILGenerator ilg = method.GetILGenerator(); //CallMethod(...) // BusObject (this) ilg.Emit(OpCodes.Ldarg_0); ilg.Emit(OpCodes.Castclass, s_dbusObjectProxyType); // Interface if (propertyMethod) { ilg.Emit(OpCodes.Ldstr, "org.freedesktop.DBus.Properties"); } else { ilg.Emit(OpCodes.Ldstr, methodDescription.Interface.Name); } // Member ilg.Emit(OpCodes.Ldstr, methodDescription.Name); // Signature if (methodDescription.InSignature.HasValue || propertyMethod) { string inSig = methodDescription.InSignature?.Value ?? string.Empty; if (propertyMethod) { inSig = "s" + inSig; } ilg.Emit(OpCodes.Ldstr, inSig); ilg.Emit(OpCodes.Newobj, s_signatureConstructor); ilg.Emit(OpCodes.Newobj, s_nullableSignatureConstructor); } else { LocalBuilder signature = ilg.DeclareLocal(s_nullableSignatureType); ilg.Emit(OpCodes.Ldloca_S, signature); ilg.Emit(OpCodes.Initobj, s_nullableSignatureType); ilg.Emit(OpCodes.Ldloc, signature); } // MessageWriter var argumentOffset = 1; //offset by one to account for "this" if (methodDescription.InArguments.Count != 0 || propertyMethod) { LocalBuilder writer = ilg.DeclareLocal(s_messageWriterType); ilg.Emit(OpCodes.Newobj, s_messageWriterConstructor); ilg.Emit(OpCodes.Stloc, writer); if (propertyMethod) { // Write parameter Type parameterType = typeof(string); ilg.Emit(OpCodes.Ldloc, writer); ilg.Emit(OpCodes.Ldstr, methodDescription.Interface.Name); ilg.Emit(OpCodes.Call, WriteMethodFactory.CreateWriteMethodForType(parameterType, isCompileTimeType: true)); } foreach (var argument in methodDescription.InArguments) { // Write parameter Type parameterType = argument.Type; ilg.Emit(OpCodes.Ldloc, writer); ilg.Emit(OpCodes.Ldarg, argumentOffset); ilg.Emit(OpCodes.Call, WriteMethodFactory.CreateWriteMethodForType(parameterType, isCompileTimeType: true)); argumentOffset++; } ilg.Emit(OpCodes.Ldloc, writer); } else { ilg.Emit(OpCodes.Ldnull); } if (methodDescription.OutType != null) { // CallMethod if (methodDescription.IsGenericOut) { Type genericParameter = method.GetGenericArguments()[0]; ilg.Emit(OpCodes.Call, s_callGenericOutMethod.MakeGenericMethod(new[] { genericParameter })); } else { // ReadMethodDelegate ilg.Emit(OpCodes.Ldnull); ilg.Emit(OpCodes.Ldftn, ReadMethodFactory.CreateReadMethodForType(methodDescription.OutType)); var readDelegateConstructor = s_readMethodDelegateGenericType.MakeGenericType(new[] { methodDescription.OutType }).GetConstructors()[0]; ilg.Emit(OpCodes.Newobj, readDelegateConstructor); ilg.Emit(OpCodes.Call, s_callNonVoidMethod.MakeGenericMethod(new[] { methodDescription.OutType })); } } else { // CallMethod ilg.Emit(OpCodes.Call, s_callVoidMethod); } ilg.Emit(OpCodes.Ret); }