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