* qt/Makfile.am:
[platform/upstream/dbus.git] / mono / ProxyBuilder.cs
index 8044909..7a3de95 100644 (file)
@@ -21,6 +21,8 @@ namespace DBus
                                                                                  new Type[0]);
     private static MethodInfo Service_AddSignalCalledMI = typeof(Service).GetMethod("add_SignalCalled",
                                                                                    new Type[] {typeof(Service.SignalCalledHandler)});
+    private static MethodInfo Service_RemoveSignalCalledMI = typeof(Service).GetMethod("remove_SignalCalled",
+                                                                                   new Type[] {typeof(Service.SignalCalledHandler)});                                                                              
     private static MethodInfo Signal_PathNameMI = typeof(Signal).GetMethod("get_PathName",
                                                                           new Type[0]);
     private static MethodInfo Message_ArgumentsMI = typeof(Message).GetMethod("get_Arguments",
@@ -35,6 +37,8 @@ namespace DBus
                                                                                             new Type[0]);
     private static MethodInfo Message_SendMI = typeof(Message).GetMethod("Send",
                                                                         new Type[0]);
+    private static MethodInfo Message_DisposeMI = typeof(Message).GetMethod("Dispose",
+                                                                           new Type[0]);
     private static MethodInfo Arguments_GetEnumeratorMI = typeof(Arguments).GetMethod("GetEnumerator",
                                                                                          new Type[0]);
     private static MethodInfo IEnumerator_MoveNextMI = typeof(System.Collections.IEnumerator).GetMethod("MoveNext",
@@ -197,7 +201,6 @@ namespace DBus
       // Generate the locals
       LocalBuilder methodCallL = generator.DeclareLocal(typeof(MethodCall));
       methodCallL.SetLocalSymInfo("signal");
-      LocalBuilder replyL = generator.DeclareLocal(typeof(MethodReturn));
 
       //generator.EmitWriteLine("Signal signal = new Signal(...)");
       generator.Emit(OpCodes.Ldsfld, serviceF);
@@ -224,6 +227,10 @@ namespace DBus
       generator.Emit(OpCodes.Ldloc_0);
       generator.EmitCall(OpCodes.Callvirt, Message_SendMI, null); 
 
+      //generator.EmitWriteLine("signal.Dispose()");
+      generator.Emit(OpCodes.Ldloc_0);
+      generator.EmitCall(OpCodes.Callvirt, Message_DisposeMI, null);
+
       //generator.EmitWriteLine("return");
       generator.Emit(OpCodes.Ret);
     }
@@ -310,6 +317,15 @@ namespace DBus
        }
       }
 
+      // Clean up after ourselves
+      //generator.EmitWriteLine("methodCall.Dispose()");
+      generator.Emit(OpCodes.Ldloc_0);
+      generator.EmitCall(OpCodes.Callvirt, Message_DisposeMI, null);
+
+      //generator.EmitWriteLine("reply.Dispose()");
+      generator.Emit(OpCodes.Ldloc_1);
+      generator.EmitCall(OpCodes.Callvirt, Message_DisposeMI, null);
+
       if (method.ReturnType != typeof(void)) {
        generator.Emit(OpCodes.Ldloc_3);
       }
@@ -388,7 +404,7 @@ namespace DBus
       }
     }
     
-    public void BuildConstructor(ref TypeBuilder typeB, FieldInfo serviceF, FieldInfo pathF, MethodInfo signalCalledMI)
+    public void BuildConstructor(ref TypeBuilder typeB, FieldInfo serviceF, FieldInfo pathF, MethodInfo signalCalledMI, FieldInfo deleF)
     {
       Type[] pars = {typeof(Service), typeof(string)};
       ConstructorBuilder constructor = typeB.DefineConstructor(MethodAttributes.RTSpecialName | 
@@ -396,6 +412,10 @@ namespace DBus
                                                               CallingConventions.Standard, pars);
 
       ILGenerator generator = constructor.GetILGenerator();
+
+      LocalBuilder handlerL = generator.DeclareLocal (typeof (Service.SignalCalledHandler));
+      handlerL.SetLocalSymInfo ("handler");
+
       generator.Emit(OpCodes.Ldarg_0);
       generator.Emit(OpCodes.Call, this.introspector.Constructor);
       //generator.EmitWriteLine("service = myService");
@@ -405,12 +425,21 @@ namespace DBus
       generator.Emit(OpCodes.Ldarg_0);
       generator.Emit(OpCodes.Ldarg_2);
       generator.Emit(OpCodes.Stfld, pathF);
-      
-      //generator.EmitWriteLine("myService.SignalCalled += new Service.SignalCalledHandler(Service_SignalCalled)");
+
+      //generator.EmitWriteLine("handler = new Service.SignalCalledHandler(Service_SignalCalled)");      
       generator.Emit(OpCodes.Ldarg_1);
       generator.Emit(OpCodes.Ldarg_0);
       generator.Emit(OpCodes.Ldftn, signalCalledMI);
       generator.Emit(OpCodes.Newobj, Service_SignalCalledHandlerC);
+      generator.Emit(OpCodes.Stloc_0);
+
+      //generator.EmitWriteLine("this.delegate_created = handler");
+      generator.Emit(OpCodes.Ldarg_0);
+      generator.Emit(OpCodes.Ldloc_0);
+      generator.Emit(OpCodes.Stfld, deleF);
+
+      //generator.EmitWriteLine("myService.SignalCalled += handler");
+      generator.Emit(OpCodes.Ldloc_0);
       generator.EmitCall(OpCodes.Callvirt, Service_AddSignalCalledMI, null);
 
       //generator.EmitWriteLine("return");
@@ -439,6 +468,30 @@ namespace DBus
       generator.Emit(OpCodes.Ret);
     }
     
+    public void BuildFinalizer (TypeBuilder tb, FieldInfo serviceF, FieldInfo deleF)
+    {
+       // Note that this is a *HORRIBLE* example of how to build a finalizer
+       // It doesn't use the try/finally to chain to Object::Finalize. However,
+       // because that is always going to be a nop, lets just ignore that here.
+       // If you are trying to find the right code, look at what mcs does ;-).
+
+       MethodBuilder mb = tb.DefineMethod("Finalize",
+                                         MethodAttributes.Family |
+                                         MethodAttributes.HideBySig |
+                                         MethodAttributes.Virtual, 
+                                         typeof (void), 
+                                         new Type [0]);
+       ILGenerator generator = mb.GetILGenerator();
+
+       //generator.EmitWriteLine("this.service.SignalCalled -= this.delegate_created");
+       generator.Emit (OpCodes.Ldarg_0);
+       generator.Emit (OpCodes.Ldfld, serviceF);
+       generator.Emit (OpCodes.Ldarg_0);
+       generator.Emit (OpCodes.Ldfld, deleF);
+       generator.EmitCall (OpCodes.Callvirt, Service_RemoveSignalCalledMI, null);
+       generator.Emit (OpCodes.Ret);
+    }
+    
     public object GetSignalProxy()
     {
       Type proxyType = Service.ProxyAssembly.GetType(ObjectName + ".SignalProxy");
@@ -502,9 +555,13 @@ namespace DBus
        FieldBuilder pathF = typeB.DefineField("pathName", 
                                               typeof(string), 
                                               FieldAttributes.Private);
+       FieldBuilder deleF = typeB.DefineField("delegate_created", 
+                                              typeof(Service.SignalCalledHandler), 
+                                              FieldAttributes.Private);
+       BuildFinalizer (typeB, serviceF, deleF);
        
        MethodInfo signalCalledMI = BuildSignalCalled(ref typeB, serviceF, pathF);
-       BuildConstructor(ref typeB, serviceF, pathF, signalCalledMI);
+       BuildConstructor(ref typeB, serviceF, pathF, signalCalledMI, deleF);
        
        // Build the methods
        foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {
@@ -522,7 +579,7 @@ namespace DBus
        // monodis. Note that in order for this to work you should copy
        // the client assembly as a dll file so that monodis can pick it
        // up.
-       //Service.ProxyAssembly.Save("proxy.dll");
+       //Service.ProxyAssembly.Save(Service.Name + ".proxy.dll");
       }
 
       Type [] parTypes = new Type[] {typeof(Service), typeof(string)};