2005-03-15 Joe Shaw <joeshaw@novell.com>
[platform/upstream/dbus.git] / mono / ProxyBuilder.cs
1 namespace DBus
2 {
3   using System;
4   using System.Runtime.InteropServices;
5   using System.Diagnostics;
6   using System.Collections;
7   using System.Threading;
8   using System.Reflection;
9   using System.Reflection.Emit;
10
11   internal class ProxyBuilder
12   {
13     private Service service= null;
14     private string pathName = null;
15     private Type type = null;
16     private Introspector introspector = null;
17     
18     private static MethodInfo Service_NameMI = typeof(Service).GetMethod("get_Name", 
19                                                                             new Type[0]);
20     private static MethodInfo Service_ConnectionMI = typeof(Service).GetMethod("get_Connection",
21                                                                                   new Type[0]);
22     private static MethodInfo Service_AddSignalCalledMI = typeof(Service).GetMethod("add_SignalCalled",
23                                                                                     new Type[] {typeof(Service.SignalCalledHandler)});
24     private static MethodInfo Service_RemoveSignalCalledMI = typeof(Service).GetMethod("remove_SignalCalled",
25                                                                                     new Type[] {typeof(Service.SignalCalledHandler)});                                                                              
26     private static MethodInfo Signal_PathNameMI = typeof(Signal).GetMethod("get_PathName",
27                                                                            new Type[0]);
28     private static MethodInfo Message_ArgumentsMI = typeof(Message).GetMethod("get_Arguments",
29                                                                                  new Type[0]);
30     private static MethodInfo Message_KeyMI = typeof(Message).GetMethod("get_Key",
31                                                                         new Type[0]);
32     private static MethodInfo Arguments_InitAppendingMI = typeof(Arguments).GetMethod("InitAppending",
33                                                                                           new Type[0]);
34     private static MethodInfo Arguments_AppendMI = typeof(Arguments).GetMethod("Append",
35                                                                                   new Type[] {typeof(DBusType.IDBusType)});
36     private static MethodInfo Message_SendWithReplyAndBlockMI = typeof(Message).GetMethod("SendWithReplyAndBlock",
37                                                                                              new Type[0]);
38     private static MethodInfo Message_SendMI = typeof(Message).GetMethod("Send",
39                                                                          new Type[0]);
40     private static MethodInfo Message_DisposeMI = typeof(Message).GetMethod("Dispose",
41                                                                             new Type[0]);
42     private static MethodInfo Arguments_GetEnumeratorMI = typeof(Arguments).GetMethod("GetEnumerator",
43                                                                                           new Type[0]);
44     private static MethodInfo IEnumerator_MoveNextMI = typeof(System.Collections.IEnumerator).GetMethod("MoveNext",
45                                                                                                         new Type[0]);
46     private static MethodInfo IEnumerator_CurrentMI = typeof(System.Collections.IEnumerator).GetMethod("get_Current",
47                                                                                                        new Type[0]);
48     private static MethodInfo Type_GetTypeFromHandleMI = typeof(System.Type).GetMethod("GetTypeFromHandle",
49                                                                                        new Type[] {typeof(System.RuntimeTypeHandle)});
50     private static MethodInfo IDBusType_GetMI = typeof(DBusType.IDBusType).GetMethod("Get",
51                                                                                      new Type[] {typeof(System.Type)});
52     private static ConstructorInfo MethodCall_C = typeof(MethodCall).GetConstructor(new Type[] {typeof(Service),
53                                                                                                 typeof(string),
54                                                                                                 typeof(string),
55                                                                                                 typeof(string)});
56     private static ConstructorInfo Signal_C = typeof(Signal).GetConstructor(new Type[] {typeof(Service),
57                                                                                         typeof(string),
58                                                                                         typeof(string),
59                                                                                         typeof(string)});
60     private static ConstructorInfo Service_SignalCalledHandlerC = typeof(Service.SignalCalledHandler).GetConstructor(new Type[] {typeof(object),
61                                                                                                                                  typeof(System.IntPtr)});
62     private static MethodInfo String_opEqualityMI = typeof(System.String).GetMethod("op_Equality",
63                                                                                     new Type[] {typeof(string),
64                                                                                                 typeof(string)});                                                                                                            
65     private static MethodInfo MulticastDelegate_opInequalityMI = typeof(System.MulticastDelegate).GetMethod("op_Inequality",
66                                                                                     new Type[] {typeof(System.MulticastDelegate),
67                                                                                                 typeof(System.MulticastDelegate)});
68     
69
70     public ProxyBuilder(Service service, Type type, string pathName)
71     {
72       this.service = service;
73       this.pathName = pathName;
74       this.type = type;
75       this.introspector = Introspector.GetIntrospector(type);
76     }
77
78     private MethodInfo BuildSignalCalled(ref TypeBuilder typeB, FieldInfo serviceF, FieldInfo pathF)
79     {
80       Type[] parTypes = {typeof(Signal)};
81       MethodBuilder methodBuilder = typeB.DefineMethod("Service_SignalCalled",
82                                                        MethodAttributes.Private |
83                                                        MethodAttributes.HideBySig,
84                                                        typeof(void),
85                                                        parTypes);
86       
87       ILGenerator generator = methodBuilder.GetILGenerator();
88
89       LocalBuilder enumeratorL = generator.DeclareLocal(typeof(System.Collections.IEnumerator));
90       enumeratorL.SetLocalSymInfo("enumerator");
91
92       Label wrongPath = generator.DefineLabel();
93       //generator.EmitWriteLine("if (signal.PathName == pathName) {");
94       generator.Emit(OpCodes.Ldarg_1);
95       generator.EmitCall(OpCodes.Callvirt, Signal_PathNameMI, null);
96       generator.Emit(OpCodes.Ldarg_0);
97       generator.Emit(OpCodes.Ldfld, pathF);
98       generator.EmitCall(OpCodes.Call, String_opEqualityMI, null);
99       generator.Emit(OpCodes.Brfalse, wrongPath);
100
101       int localOffset = 1;
102
103       foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {
104         InterfaceProxy interfaceProxy = (InterfaceProxy) interfaceEntry.Value;
105         foreach (DictionaryEntry signalEntry in interfaceProxy.Signals) {
106           EventInfo eventE = (EventInfo) signalEntry.Value;
107           // This is really cheeky since we need to grab the event as a private field.
108           FieldInfo eventF = this.type.GetField(eventE.Name,
109                                                 BindingFlags.NonPublic|
110                                                 BindingFlags.Instance);
111
112           MethodInfo eventHandler_InvokeMI = eventE.EventHandlerType.GetMethod("Invoke");
113
114           ParameterInfo[] pars = eventHandler_InvokeMI.GetParameters();
115           parTypes = new Type[pars.Length];
116           for (int parN = 0; parN < pars.Length; parN++) {
117             parTypes[parN] = pars[parN].ParameterType;
118             LocalBuilder parmL = generator.DeclareLocal(parTypes[parN]);
119             parmL.SetLocalSymInfo(pars[parN].Name);
120           }
121           
122           Label skip = generator.DefineLabel();      
123           //generator.EmitWriteLine("  if (SelectedIndexChanged != null) {");
124           generator.Emit(OpCodes.Ldarg_0);
125           generator.Emit(OpCodes.Ldfld, eventF);
126           generator.Emit(OpCodes.Ldnull);
127           generator.EmitCall(OpCodes.Call, MulticastDelegate_opInequalityMI, null);
128           generator.Emit(OpCodes.Brfalse, skip);
129           
130           //generator.EmitWriteLine("    if (signal.Key == 'la i')");
131           generator.Emit(OpCodes.Ldarg_1);
132           generator.EmitCall(OpCodes.Callvirt, Message_KeyMI, null);
133           generator.Emit(OpCodes.Ldstr, eventE.Name + " " + InterfaceProxy.GetSignature(eventHandler_InvokeMI));
134           generator.EmitCall(OpCodes.Call, String_opEqualityMI, null);
135           generator.Emit(OpCodes.Brfalse, skip);
136
137           //generator.EmitWriteLine("IEnumerator enumerator = signal.Arguments.GetEnumerator()");
138           generator.Emit(OpCodes.Ldarg_1);
139           generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
140           generator.EmitCall(OpCodes.Callvirt, Arguments_GetEnumeratorMI, null);
141           generator.Emit(OpCodes.Stloc_0);
142           
143           for (int parN = 0; parN < pars.Length; parN++) {
144             ParameterInfo par = pars[parN];
145             if (!par.IsOut) {
146               EmitSignalIn(generator, par.ParameterType, parN + localOffset, serviceF);
147             }
148           }
149           
150           //generator.EmitWriteLine("    SelectedIndexChanged(selectedIndex)");
151           generator.Emit(OpCodes.Ldarg_0);
152           generator.Emit(OpCodes.Ldfld, eventF);
153           for (int parN = 0; parN < pars.Length; parN++) {
154             generator.Emit(OpCodes.Ldloc_S, parN + localOffset);
155           }
156           
157           generator.EmitCall(OpCodes.Callvirt, eventHandler_InvokeMI, null);
158           
159           generator.MarkLabel(skip);
160           //generator.EmitWriteLine("  }");
161           
162           localOffset += pars.Length;
163         }
164       }
165
166       generator.MarkLabel(wrongPath);
167       //generator.EmitWriteLine("}");
168
169       //generator.EmitWriteLine("return");
170       generator.Emit(OpCodes.Ret);
171
172       return methodBuilder;
173     }
174     
175     private void BuildSignalHandler(EventInfo eventE, 
176                                     InterfaceProxy interfaceProxy,
177                                     ref TypeBuilder typeB, 
178                                     FieldInfo serviceF,
179                                     FieldInfo pathF)
180     {
181       MethodInfo eventHandler_InvokeMI = eventE.EventHandlerType.GetMethod("Invoke");
182       ParameterInfo[] pars = eventHandler_InvokeMI.GetParameters();
183       Type[] parTypes = new Type[pars.Length];
184       for (int parN = 0; parN < pars.Length; parN++) {
185         parTypes[parN] = pars[parN].ParameterType;
186       }
187
188       // Generate the code
189       MethodBuilder methodBuilder = typeB.DefineMethod("Proxy_" + eventE.Name, 
190                                                        MethodAttributes.Public |
191                                                        MethodAttributes.HideBySig |
192                                                        MethodAttributes.Virtual, 
193                                                        typeof(void),
194                                                        parTypes);
195       ILGenerator generator = methodBuilder.GetILGenerator();
196
197       for (int parN = 0; parN < pars.Length; parN++) {
198         methodBuilder.DefineParameter(parN + 1, pars[parN].Attributes, pars[parN].Name);
199       }
200
201       // Generate the locals
202       LocalBuilder methodCallL = generator.DeclareLocal(typeof(MethodCall));
203       methodCallL.SetLocalSymInfo("signal");
204
205       //generator.EmitWriteLine("Signal signal = new Signal(...)");
206       generator.Emit(OpCodes.Ldsfld, serviceF);
207       generator.Emit(OpCodes.Ldarg_0);
208       generator.Emit(OpCodes.Ldfld, pathF);
209       generator.Emit(OpCodes.Ldstr, interfaceProxy.InterfaceName);
210       generator.Emit(OpCodes.Ldstr, eventE.Name);
211       generator.Emit(OpCodes.Newobj, Signal_C);
212       generator.Emit(OpCodes.Stloc_0);
213
214       //generator.EmitWriteLine("signal.Arguments.InitAppending()");
215       generator.Emit(OpCodes.Ldloc_0);
216       generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
217       generator.EmitCall(OpCodes.Callvirt, Arguments_InitAppendingMI, null);
218
219       for (int parN = 0; parN < pars.Length; parN++) {
220         ParameterInfo par = pars[parN];
221         if (!par.IsOut) {
222           EmitIn(generator, par.ParameterType, parN, serviceF);
223         }
224       }
225       
226       //generator.EmitWriteLine("signal.Send()");
227       generator.Emit(OpCodes.Ldloc_0);
228       generator.EmitCall(OpCodes.Callvirt, Message_SendMI, null); 
229
230       //generator.EmitWriteLine("signal.Dispose()");
231       generator.Emit(OpCodes.Ldloc_0);
232       generator.EmitCall(OpCodes.Callvirt, Message_DisposeMI, null);
233
234       //generator.EmitWriteLine("return");
235       generator.Emit(OpCodes.Ret);
236     }
237
238     private void BuildMethod(MethodInfo method, 
239                              InterfaceProxy interfaceProxy,
240                              ref TypeBuilder typeB, 
241                              FieldInfo serviceF,
242                              FieldInfo pathF)
243     {
244       ParameterInfo[] pars = method.GetParameters();
245       Type[] parTypes = new Type[pars.Length];
246       for (int parN = 0; parN < pars.Length; parN++) {
247         parTypes[parN] = pars[parN].ParameterType;
248       }
249
250       // Generate the code
251       MethodBuilder methodBuilder = typeB.DefineMethod(method.Name, 
252                                                        MethodAttributes.Public |
253                                                        MethodAttributes.HideBySig |
254                                                        MethodAttributes.Virtual, 
255                                                        method.ReturnType, 
256                                                        parTypes);
257       ILGenerator generator = methodBuilder.GetILGenerator();
258
259       for (int parN = 0; parN < pars.Length; parN++) {
260         methodBuilder.DefineParameter(parN + 1, pars[parN].Attributes, pars[parN].Name);
261       }
262
263       // Generate the locals
264       LocalBuilder methodCallL = generator.DeclareLocal(typeof(MethodCall));
265       methodCallL.SetLocalSymInfo("methodCall");
266       LocalBuilder replyL = generator.DeclareLocal(typeof(MethodReturn));
267       replyL.SetLocalSymInfo("reply");
268       LocalBuilder enumeratorL = generator.DeclareLocal(typeof(System.Collections.IEnumerator));
269       enumeratorL.SetLocalSymInfo("enumerator");
270
271       if (method.ReturnType != typeof(void)) {
272         LocalBuilder retvalL = generator.DeclareLocal(method.ReturnType);
273         retvalL.SetLocalSymInfo("retval");
274       }
275
276       //generator.EmitWriteLine("MethodCall methodCall = new MethodCall(...)");
277       generator.Emit(OpCodes.Ldsfld, serviceF);
278       generator.Emit(OpCodes.Ldarg_0);
279       generator.Emit(OpCodes.Ldfld, pathF);
280       generator.Emit(OpCodes.Ldstr, interfaceProxy.InterfaceName);
281       generator.Emit(OpCodes.Ldstr, method.Name);
282       generator.Emit(OpCodes.Newobj, MethodCall_C);
283       generator.Emit(OpCodes.Stloc_0);
284
285       //generator.EmitWriteLine("methodCall.Arguments.InitAppending()");
286       generator.Emit(OpCodes.Ldloc_0);
287       generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
288       generator.EmitCall(OpCodes.Callvirt, Arguments_InitAppendingMI, null);
289
290       for (int parN = 0; parN < pars.Length; parN++) {
291         ParameterInfo par = pars[parN];
292         if (!par.IsOut) {
293           EmitIn(generator, par.ParameterType, parN, serviceF);
294         }
295       }
296       
297       //generator.EmitWriteLine("MethodReturn reply = methodCall.SendWithReplyAndBlock()");
298       generator.Emit(OpCodes.Ldloc_0);
299       generator.EmitCall(OpCodes.Callvirt, Message_SendWithReplyAndBlockMI, null);      
300       generator.Emit(OpCodes.Stloc_1);
301
302       //generator.EmitWriteLine("IEnumerator enumeartor = reply.Arguments.GetEnumerator()");
303       generator.Emit(OpCodes.Ldloc_1);
304       generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
305       generator.EmitCall(OpCodes.Callvirt, Arguments_GetEnumeratorMI, null);
306       generator.Emit(OpCodes.Stloc_2);
307
308       // handle the return value
309       if (method.ReturnType != typeof(void)) {
310         EmitOut(generator, method.ReturnType, 0);
311       }
312
313       for (int parN = 0; parN < pars.Length; parN++) {
314         ParameterInfo par = pars[parN];
315         if (par.IsOut || par.ParameterType.ToString().EndsWith("&")) {
316           EmitOut(generator, par.ParameterType, parN);
317         }
318       }
319
320       // Clean up after ourselves
321       //generator.EmitWriteLine("methodCall.Dispose()");
322       generator.Emit(OpCodes.Ldloc_0);
323       generator.EmitCall(OpCodes.Callvirt, Message_DisposeMI, null);
324
325       //generator.EmitWriteLine("reply.Dispose()");
326       generator.Emit(OpCodes.Ldloc_1);
327       generator.EmitCall(OpCodes.Callvirt, Message_DisposeMI, null);
328
329       if (method.ReturnType != typeof(void)) {
330         generator.Emit(OpCodes.Ldloc_3);
331       }
332       
333       generator.Emit(OpCodes.Ret);
334
335       // Generate the method
336       typeB.DefineMethodOverride(methodBuilder, method);
337     }
338
339     private void EmitSignalIn(ILGenerator generator, Type parType, int parN, FieldInfo serviceF)
340     {
341         //generator.EmitWriteLine("enumerator.MoveNext()");
342         generator.Emit(OpCodes.Ldloc_0);
343         generator.EmitCall(OpCodes.Callvirt, IEnumerator_MoveNextMI, null);
344         
345         Type outParType = Arguments.MatchType(parType);
346         //generator.EmitWriteLine("int selectedIndex = (int) ((DBusType.IDBusType) enumerator.Current).Get(typeof(int))");
347         generator.Emit(OpCodes.Pop);
348         generator.Emit(OpCodes.Ldloc_0);
349         generator.EmitCall(OpCodes.Callvirt, IEnumerator_CurrentMI, null);
350         generator.Emit(OpCodes.Castclass, typeof(DBusType.IDBusType));
351         generator.Emit(OpCodes.Ldtoken, parType);
352         generator.EmitCall(OpCodes.Call, Type_GetTypeFromHandleMI, null);
353         generator.EmitCall(OpCodes.Callvirt, IDBusType_GetMI, null);
354         // Call the DBusType EmitMarshalOut to make it emit itself
355         object[] pars = new object[] {generator, parType, true};
356         outParType.InvokeMember("EmitMarshalOut", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, pars, null);
357         generator.Emit(OpCodes.Stloc_S, parN);
358     }
359     
360
361     private void EmitIn(ILGenerator generator, Type parType, int parN, FieldInfo serviceF)
362     {
363       Type inParType = Arguments.MatchType(parType);
364       //generator.EmitWriteLine("methodCall.Arguments.Append(...)");
365       generator.Emit(OpCodes.Ldloc_0);
366       generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
367       generator.Emit(OpCodes.Ldarg_S, parN + 1);
368
369       // Call the DBusType EmitMarshalIn to make it emit itself
370       object[] pars = new object[] {generator, parType};
371       inParType.InvokeMember("EmitMarshalIn", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, pars, null);
372
373       generator.Emit(OpCodes.Ldsfld, serviceF);
374       generator.Emit(OpCodes.Newobj, Arguments.GetDBusTypeConstructor(inParType, parType));
375       generator.EmitCall(OpCodes.Callvirt, Arguments_AppendMI, null);
376     }
377
378     private void EmitOut(ILGenerator generator, Type parType, int parN)
379     {
380       Type outParType = Arguments.MatchType(parType);
381       //generator.EmitWriteLine("enumerator.MoveNext()");
382       generator.Emit(OpCodes.Ldloc_2);
383       generator.EmitCall(OpCodes.Callvirt, IEnumerator_MoveNextMI, null);
384
385       //generator.EmitWriteLine("return (" + parType + ") ((DBusType.IDBusType) enumerator.Current).Get(typeof(" + parType + "))");
386       generator.Emit(OpCodes.Pop);
387       if (parN > 0) {
388         generator.Emit(OpCodes.Ldarg_S, parN + 1);
389       }
390       
391       generator.Emit(OpCodes.Ldloc_2);
392       generator.EmitCall(OpCodes.Callvirt, IEnumerator_CurrentMI, null);
393       generator.Emit(OpCodes.Castclass, typeof(DBusType.IDBusType));
394       generator.Emit(OpCodes.Ldtoken, parType);
395       generator.EmitCall(OpCodes.Call, Type_GetTypeFromHandleMI, null);
396       generator.EmitCall(OpCodes.Callvirt, IDBusType_GetMI, null);
397
398       // Call the DBusType EmitMarshalOut to make it emit itself
399       object[] pars = new object[] {generator, parType, parN == 0};
400       outParType.InvokeMember("EmitMarshalOut", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, pars, null);
401       
402       if (parN == 0) {
403         generator.Emit(OpCodes.Stloc_3);
404       }
405     }
406     
407     public void BuildConstructor(ref TypeBuilder typeB, FieldInfo serviceF, FieldInfo pathF, MethodInfo signalCalledMI, FieldInfo deleF)
408     {
409       Type[] pars = {typeof(Service), typeof(string)};
410       ConstructorBuilder constructor = typeB.DefineConstructor(MethodAttributes.RTSpecialName | 
411                                                                MethodAttributes.Public,
412                                                                CallingConventions.Standard, pars);
413
414       ILGenerator generator = constructor.GetILGenerator();
415
416       LocalBuilder handlerL = generator.DeclareLocal (typeof (Service.SignalCalledHandler));
417       handlerL.SetLocalSymInfo ("handler");
418
419       generator.Emit(OpCodes.Ldarg_0);
420       generator.Emit(OpCodes.Call, this.introspector.Constructor);
421       //generator.EmitWriteLine("service = myService");
422       generator.Emit(OpCodes.Ldarg_1);
423       generator.Emit(OpCodes.Stsfld, serviceF);
424       //generator.EmitWriteLine("this.pathName = pathName");
425       generator.Emit(OpCodes.Ldarg_0);
426       generator.Emit(OpCodes.Ldarg_2);
427       generator.Emit(OpCodes.Stfld, pathF);
428
429       //generator.EmitWriteLine("handler = new Service.SignalCalledHandler(Service_SignalCalled)");      
430       generator.Emit(OpCodes.Ldarg_1);
431       generator.Emit(OpCodes.Ldarg_0);
432       generator.Emit(OpCodes.Ldftn, signalCalledMI);
433       generator.Emit(OpCodes.Newobj, Service_SignalCalledHandlerC);
434       generator.Emit(OpCodes.Stloc_0);
435
436       //generator.EmitWriteLine("this.delegate_created = handler");
437       generator.Emit(OpCodes.Ldarg_0);
438       generator.Emit(OpCodes.Ldloc_0);
439       generator.Emit(OpCodes.Stfld, deleF);
440
441       //generator.EmitWriteLine("myService.SignalCalled += handler");
442       generator.Emit(OpCodes.Ldloc_0);
443       generator.EmitCall(OpCodes.Callvirt, Service_AddSignalCalledMI, null);
444
445       //generator.EmitWriteLine("return");
446       generator.Emit(OpCodes.Ret);
447     }
448
449     public void BuildSignalConstructor(ref TypeBuilder typeB, FieldInfo serviceF, FieldInfo pathF)
450     {
451       Type[] pars = {typeof(Service), typeof(string)};
452       ConstructorBuilder constructor = typeB.DefineConstructor(MethodAttributes.RTSpecialName | 
453                                                                MethodAttributes.Public,
454                                                                CallingConventions.Standard, pars);
455
456       ILGenerator generator = constructor.GetILGenerator();
457       generator.Emit(OpCodes.Ldarg_0);
458       generator.Emit(OpCodes.Call, this.introspector.Constructor);
459       //generator.EmitWriteLine("service = myService");
460       generator.Emit(OpCodes.Ldarg_1);
461       generator.Emit(OpCodes.Stsfld, serviceF);
462       //generator.EmitWriteLine("this.pathName = pathName");
463       generator.Emit(OpCodes.Ldarg_0);
464       generator.Emit(OpCodes.Ldarg_2);
465       generator.Emit(OpCodes.Stfld, pathF);
466       
467       //generator.EmitWriteLine("return");
468       generator.Emit(OpCodes.Ret);
469     }
470     
471     public void BuildFinalizer (TypeBuilder tb, FieldInfo serviceF, FieldInfo deleF)
472     {
473        // Note that this is a *HORRIBLE* example of how to build a finalizer
474        // It doesn't use the try/finally to chain to Object::Finalize. However,
475        // because that is always going to be a nop, lets just ignore that here.
476        // If you are trying to find the right code, look at what mcs does ;-).
477
478        MethodBuilder mb = tb.DefineMethod("Finalize",
479                                           MethodAttributes.Family |
480                                           MethodAttributes.HideBySig |
481                                           MethodAttributes.Virtual, 
482                                           typeof (void), 
483                                           new Type [0]);
484        ILGenerator generator = mb.GetILGenerator();
485
486        //generator.EmitWriteLine("this.service.SignalCalled -= this.delegate_created");
487        generator.Emit (OpCodes.Ldarg_0);
488        generator.Emit (OpCodes.Ldfld, serviceF);
489        generator.Emit (OpCodes.Ldarg_0);
490        generator.Emit (OpCodes.Ldfld, deleF);
491        generator.EmitCall (OpCodes.Callvirt, Service_RemoveSignalCalledMI, null);
492        generator.Emit (OpCodes.Ret);
493     }
494     
495     public object GetSignalProxy()
496     {
497       Type proxyType = Service.ProxyAssembly.GetType(ObjectName + ".SignalProxy");
498
499       if (proxyType == null) {
500         // Build the type
501         TypeBuilder typeB = Service.Module.DefineType(ObjectName + ".SignalProxy", 
502                                                       TypeAttributes.Public, 
503                                                       this.type);
504         
505         FieldBuilder serviceF = typeB.DefineField("service", 
506                                                   typeof(Service), 
507                                                   FieldAttributes.Private | 
508                                                   FieldAttributes.Static);
509         FieldBuilder pathF = typeB.DefineField("pathName", 
510                                                typeof(string), 
511                                                FieldAttributes.Private);
512
513         BuildSignalConstructor(ref typeB, serviceF, pathF);
514         
515         // Build the signal handlers
516         foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {
517           InterfaceProxy interfaceProxy = (InterfaceProxy) interfaceEntry.Value;
518           foreach (DictionaryEntry signalEntry in interfaceProxy.Signals) {
519             EventInfo eventE = (EventInfo) signalEntry.Value;
520             BuildSignalHandler(eventE, interfaceProxy, ref typeB, serviceF, pathF);
521           }
522         }
523         
524         proxyType = typeB.CreateType();
525       
526         // Uncomment the following line to produce a DLL of the
527         // constructed assembly which can then be examined using
528         // monodis. Note that in order for this to work you should copy
529         // the client assembly as a dll file so that monodis can pick it
530         // up.
531         //Service.ProxyAssembly.Save("proxy.dll");
532       }
533
534       Type [] parTypes = new Type[] {typeof(Service), typeof(string)};
535       object [] pars = new object[] {Service, pathName};
536       
537       ConstructorInfo constructor = proxyType.GetConstructor(parTypes);
538       object instance = constructor.Invoke(pars);
539       return instance;
540     }
541       
542     
543     public object GetProxy() 
544     { 
545       Type proxyType = Service.ProxyAssembly.GetType(ObjectName + ".Proxy");
546       
547       if (proxyType == null) {
548         // Build the type
549         TypeBuilder typeB = Service.Module.DefineType(ObjectName + ".Proxy", TypeAttributes.Public, this.type);
550         
551         FieldBuilder serviceF = typeB.DefineField("service", 
552                                                   typeof(Service), 
553                                                   FieldAttributes.Private | 
554                                                   FieldAttributes.Static);
555         FieldBuilder pathF = typeB.DefineField("pathName", 
556                                                typeof(string), 
557                                                FieldAttributes.Private);
558         FieldBuilder deleF = typeB.DefineField("delegate_created", 
559                                                typeof(Service.SignalCalledHandler), 
560                                                FieldAttributes.Private);
561         BuildFinalizer (typeB, serviceF, deleF);
562         
563         MethodInfo signalCalledMI = BuildSignalCalled(ref typeB, serviceF, pathF);
564         BuildConstructor(ref typeB, serviceF, pathF, signalCalledMI, deleF);
565         
566         // Build the methods
567         foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {
568           InterfaceProxy interfaceProxy = (InterfaceProxy) interfaceEntry.Value;
569           foreach (DictionaryEntry methodEntry in interfaceProxy.Methods) {
570             MethodInfo method = (MethodInfo) methodEntry.Value;
571             BuildMethod(method, interfaceProxy, ref typeB, serviceF, pathF);
572           }
573         }
574         
575         proxyType = typeB.CreateType();
576       
577         // Uncomment the following line to produce a DLL of the
578         // constructed assembly which can then be examined using
579         // monodis. Note that in order for this to work you should copy
580         // the client assembly as a dll file so that monodis can pick it
581         // up.
582         //Service.ProxyAssembly.Save(Service.Name + ".proxy.dll");
583       }
584
585       Type [] parTypes = new Type[] {typeof(Service), typeof(string)};
586       object [] pars = new object[] {Service, pathName};
587       
588       ConstructorInfo constructor = proxyType.GetConstructor(parTypes);
589       object instance = constructor.Invoke(pars);
590       return instance;
591     }
592     
593     private Service Service
594     {
595       get {
596         return this.service;
597       }
598     }
599
600     private string ObjectName
601     {
602       get {
603         return this.introspector.ToString();
604       }
605     }
606   }
607 }
608