2005-03-12 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       generator.Emit(OpCodes.Ldarg_0);
416       generator.Emit(OpCodes.Call, this.introspector.Constructor);
417       //generator.EmitWriteLine("service = myService");
418       generator.Emit(OpCodes.Ldarg_1);
419       generator.Emit(OpCodes.Stsfld, serviceF);
420       //generator.EmitWriteLine("this.pathName = pathName");
421       generator.Emit(OpCodes.Ldarg_0);
422       generator.Emit(OpCodes.Ldarg_2);
423       generator.Emit(OpCodes.Stfld, pathF);
424
425       //generator.EmitWriteLine("this.delegate_created = new Service.SignalCalledHandler(Service_SignalCalled)");      
426       generator.Emit(OpCodes.Ldarg_1);
427       generator.Emit(OpCodes.Ldarg_0);
428       generator.Emit(OpCodes.Ldftn, signalCalledMI);
429       generator.Emit(OpCodes.Newobj, Service_SignalCalledHandlerC);
430       generator.Emit(OpCodes.Stloc_0);
431       generator.Emit(OpCodes.Ldarg_0);
432       generator.Emit(OpCodes.Ldloc_0);
433       generator.Emit(OpCodes.Stfld, deleF);
434
435       //generator.EmitWriteLine("myService.SignalCalled += this.delegate_created");
436       generator.Emit(OpCodes.Ldloc_0);
437       generator.EmitCall(OpCodes.Callvirt, Service_AddSignalCalledMI, null);
438
439       //generator.EmitWriteLine("return");
440       generator.Emit(OpCodes.Ret);
441     }
442
443     public void BuildSignalConstructor(ref TypeBuilder typeB, FieldInfo serviceF, FieldInfo pathF)
444     {
445       Type[] pars = {typeof(Service), typeof(string)};
446       ConstructorBuilder constructor = typeB.DefineConstructor(MethodAttributes.RTSpecialName | 
447                                                                MethodAttributes.Public,
448                                                                CallingConventions.Standard, pars);
449
450       ILGenerator generator = constructor.GetILGenerator();
451       generator.Emit(OpCodes.Ldarg_0);
452       generator.Emit(OpCodes.Call, this.introspector.Constructor);
453       //generator.EmitWriteLine("service = myService");
454       generator.Emit(OpCodes.Ldarg_1);
455       generator.Emit(OpCodes.Stsfld, serviceF);
456       //generator.EmitWriteLine("this.pathName = pathName");
457       generator.Emit(OpCodes.Ldarg_0);
458       generator.Emit(OpCodes.Ldarg_2);
459       generator.Emit(OpCodes.Stfld, pathF);
460       
461       //generator.EmitWriteLine("return");
462       generator.Emit(OpCodes.Ret);
463     }
464     
465     public void BuildFinalizer (TypeBuilder tb, FieldInfo fi)
466     {
467        // Note that this is a *HORRIBLE* example of how to build a finalizer
468        // It doesn't use the try/finally to chain to Object::Finalize. However,
469        // because that is always going to be a nop, lets just ignore that here.
470        // If you are trying to find the right code, look at what mcs does ;-).
471
472        MethodBuilder mb = tb.DefineMethod("Finalize", 
473                                           MethodAttributes.Family |
474                                           MethodAttributes.HideBySig |
475                                           MethodAttributes.Virtual, 
476                                           typeof (void), 
477                                           new Type [0]);
478        ILGenerator generator = mb.GetILGenerator();
479
480        //generator.EmitWriteLine("this.service.SignalCalled -= this.delegate_created");
481        generator.Emit (OpCodes.Ldarg_0);
482        generator.Emit (OpCodes.Ldfld, fi);
483        generator.Emit (OpCodes.Call, Service_RemoveSignalCalledMI);
484        generator.Emit (OpCodes.Ret);
485     }
486     
487     public object GetSignalProxy()
488     {
489       Type proxyType = Service.ProxyAssembly.GetType(ObjectName + ".SignalProxy");
490
491       if (proxyType == null) {
492         // Build the type
493         TypeBuilder typeB = Service.Module.DefineType(ObjectName + ".SignalProxy", 
494                                                       TypeAttributes.Public, 
495                                                       this.type);
496         
497         FieldBuilder serviceF = typeB.DefineField("service", 
498                                                   typeof(Service), 
499                                                   FieldAttributes.Private | 
500                                                   FieldAttributes.Static);
501         FieldBuilder pathF = typeB.DefineField("pathName", 
502                                                typeof(string), 
503                                                FieldAttributes.Private);
504
505         BuildSignalConstructor(ref typeB, serviceF, pathF);
506         
507         // Build the signal handlers
508         foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {
509           InterfaceProxy interfaceProxy = (InterfaceProxy) interfaceEntry.Value;
510           foreach (DictionaryEntry signalEntry in interfaceProxy.Signals) {
511             EventInfo eventE = (EventInfo) signalEntry.Value;
512             BuildSignalHandler(eventE, interfaceProxy, ref typeB, serviceF, pathF);
513           }
514         }
515         
516         proxyType = typeB.CreateType();
517       
518         // Uncomment the following line to produce a DLL of the
519         // constructed assembly which can then be examined using
520         // monodis. Note that in order for this to work you should copy
521         // the client assembly as a dll file so that monodis can pick it
522         // up.
523         //Service.ProxyAssembly.Save("proxy.dll");
524       }
525
526       Type [] parTypes = new Type[] {typeof(Service), typeof(string)};
527       object [] pars = new object[] {Service, pathName};
528       
529       ConstructorInfo constructor = proxyType.GetConstructor(parTypes);
530       object instance = constructor.Invoke(pars);
531       return instance;
532     }
533       
534     
535     public object GetProxy() 
536     { 
537       Type proxyType = Service.ProxyAssembly.GetType(ObjectName + ".Proxy");
538       
539       if (proxyType == null) {
540         // Build the type
541         TypeBuilder typeB = Service.Module.DefineType(ObjectName + ".Proxy", TypeAttributes.Public, this.type);
542         
543         FieldBuilder serviceF = typeB.DefineField("service", 
544                                                   typeof(Service), 
545                                                   FieldAttributes.Private | 
546                                                   FieldAttributes.Static);
547         FieldBuilder pathF = typeB.DefineField("pathName", 
548                                                typeof(string), 
549                                                FieldAttributes.Private);
550         FieldBuilder deleF = typeB.DefineField("delegate_created", 
551                                                typeof(Service.SignalCalledHandler), 
552                                                FieldAttributes.Private);
553         BuildFinalizer (typeB, deleF);
554         
555         MethodInfo signalCalledMI = BuildSignalCalled(ref typeB, serviceF, pathF);
556         BuildConstructor(ref typeB, serviceF, pathF, signalCalledMI, deleF);
557         
558         // Build the methods
559         foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {
560           InterfaceProxy interfaceProxy = (InterfaceProxy) interfaceEntry.Value;
561           foreach (DictionaryEntry methodEntry in interfaceProxy.Methods) {
562             MethodInfo method = (MethodInfo) methodEntry.Value;
563             BuildMethod(method, interfaceProxy, ref typeB, serviceF, pathF);
564           }
565         }
566         
567         proxyType = typeB.CreateType();
568       
569         // Uncomment the following line to produce a DLL of the
570         // constructed assembly which can then be examined using
571         // monodis. Note that in order for this to work you should copy
572         // the client assembly as a dll file so that monodis can pick it
573         // up.
574         //Service.ProxyAssembly.Save("proxy.dll");
575       }
576
577       Type [] parTypes = new Type[] {typeof(Service), typeof(string)};
578       object [] pars = new object[] {Service, pathName};
579       
580       ConstructorInfo constructor = proxyType.GetConstructor(parTypes);
581       object instance = constructor.Invoke(pars);
582       return instance;
583     }
584     
585     private Service Service
586     {
587       get {
588         return this.service;
589       }
590     }
591
592     private string ObjectName
593     {
594       get {
595         return this.introspector.ToString();
596       }
597     }
598   }
599 }
600