Main Page | Modules | Namespace List | Class Hierarchy | Data Structures | Directories | File List | Namespace Members | Data Fields | Related Pages

ProxyBuilder.cs

00001 namespace DBus
00002 {
00003   using System;
00004   using System.Runtime.InteropServices;
00005   using System.Diagnostics;
00006   using System.Collections;
00007   using System.Threading;
00008   using System.Reflection;
00009   using System.Reflection.Emit;
00010 
00011   internal class ProxyBuilder
00012   {
00013     private Service service= null;
00014     private string pathName = null;
00015     private Type type = null;
00016     private Introspector introspector = null;
00017     
00018     private static MethodInfo Service_NameMI = typeof(Service).GetMethod("get_Name", 
00019                                                                             new Type[0]);
00020     private static MethodInfo Service_ConnectionMI = typeof(Service).GetMethod("get_Connection",
00021                                                                                   new Type[0]);
00022     private static MethodInfo Service_AddSignalCalledMI = typeof(Service).GetMethod("add_SignalCalled",
00023                                                                                     new Type[] {typeof(Service.SignalCalledHandler)});
00024     private static MethodInfo Service_RemoveSignalCalledMI = typeof(Service).GetMethod("remove_SignalCalled",
00025                                                                                     new Type[] {typeof(Service.SignalCalledHandler)});                                                                              
00026     private static MethodInfo Signal_PathNameMI = typeof(Signal).GetMethod("get_PathName",
00027                                                                            new Type[0]);
00028     private static MethodInfo Message_ArgumentsMI = typeof(Message).GetMethod("get_Arguments",
00029                                                                                  new Type[0]);
00030     private static MethodInfo Message_KeyMI = typeof(Message).GetMethod("get_Key",
00031                                                                         new Type[0]);
00032     private static MethodInfo Arguments_InitAppendingMI = typeof(Arguments).GetMethod("InitAppending",
00033                                                                                           new Type[0]);
00034     private static MethodInfo Arguments_AppendMI = typeof(Arguments).GetMethod("Append",
00035                                                                                   new Type[] {typeof(DBusType.IDBusType)});
00036     private static MethodInfo Message_SendWithReplyAndBlockMI = typeof(Message).GetMethod("SendWithReplyAndBlock",
00037                                                                                              new Type[0]);
00038     private static MethodInfo Message_SendMI = typeof(Message).GetMethod("Send",
00039                                                                          new Type[0]);
00040     private static MethodInfo Message_DisposeMI = typeof(Message).GetMethod("Dispose",
00041                                                                             new Type[0]);
00042     private static MethodInfo Arguments_GetEnumeratorMI = typeof(Arguments).GetMethod("GetEnumerator",
00043                                                                                           new Type[0]);
00044     private static MethodInfo IEnumerator_MoveNextMI = typeof(System.Collections.IEnumerator).GetMethod("MoveNext",
00045                                                                                                         new Type[0]);
00046     private static MethodInfo IEnumerator_CurrentMI = typeof(System.Collections.IEnumerator).GetMethod("get_Current",
00047                                                                                                        new Type[0]);
00048     private static MethodInfo Type_GetTypeFromHandleMI = typeof(System.Type).GetMethod("GetTypeFromHandle",
00049                                                                                        new Type[] {typeof(System.RuntimeTypeHandle)});
00050     private static MethodInfo IDBusType_GetMI = typeof(DBusType.IDBusType).GetMethod("Get",
00051                                                                                      new Type[] {typeof(System.Type)});
00052     private static ConstructorInfo MethodCall_C = typeof(MethodCall).GetConstructor(new Type[] {typeof(Service),
00053                                                                                                 typeof(string),
00054                                                                                                 typeof(string),
00055                                                                                                 typeof(string)});
00056     private static ConstructorInfo Signal_C = typeof(Signal).GetConstructor(new Type[] {typeof(Service),
00057                                                                                         typeof(string),
00058                                                                                         typeof(string),
00059                                                                                         typeof(string)});
00060     private static ConstructorInfo Service_SignalCalledHandlerC = typeof(Service.SignalCalledHandler).GetConstructor(new Type[] {typeof(object),
00061                                                                                                                                  typeof(System.IntPtr)});
00062     private static MethodInfo String_opEqualityMI = typeof(System.String).GetMethod("op_Equality",
00063                                                                                     new Type[] {typeof(string),
00064                                                                                                 typeof(string)});                                                                                                            
00065     private static MethodInfo MulticastDelegate_opInequalityMI = typeof(System.MulticastDelegate).GetMethod("op_Inequality",
00066                                                                                     new Type[] {typeof(System.MulticastDelegate),
00067                                                                                                 typeof(System.MulticastDelegate)});
00068     
00069 
00070     public ProxyBuilder(Service service, Type type, string pathName)
00071     {
00072       this.service = service;
00073       this.pathName = pathName;
00074       this.type = type;
00075       this.introspector = Introspector.GetIntrospector(type);
00076     }
00077 
00078     private MethodInfo BuildSignalCalled(ref TypeBuilder typeB, FieldInfo serviceF, FieldInfo pathF)
00079     {
00080       Type[] parTypes = {typeof(Signal)};
00081       MethodBuilder methodBuilder = typeB.DefineMethod("Service_SignalCalled",
00082                                                        MethodAttributes.Private |
00083                                                        MethodAttributes.HideBySig,
00084                                                        typeof(void),
00085                                                        parTypes);
00086       
00087       ILGenerator generator = methodBuilder.GetILGenerator();
00088 
00089       LocalBuilder enumeratorL = generator.DeclareLocal(typeof(System.Collections.IEnumerator));
00090       enumeratorL.SetLocalSymInfo("enumerator");
00091 
00092       Label wrongPath = generator.DefineLabel();
00093       //generator.EmitWriteLine("if (signal.PathName == pathName) {");
00094       generator.Emit(OpCodes.Ldarg_1);
00095       generator.EmitCall(OpCodes.Callvirt, Signal_PathNameMI, null);
00096       generator.Emit(OpCodes.Ldarg_0);
00097       generator.Emit(OpCodes.Ldfld, pathF);
00098       generator.EmitCall(OpCodes.Call, String_opEqualityMI, null);
00099       generator.Emit(OpCodes.Brfalse, wrongPath);
00100 
00101       int localOffset = 1;
00102 
00103       foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {
00104         InterfaceProxy interfaceProxy = (InterfaceProxy) interfaceEntry.Value;
00105         foreach (DictionaryEntry signalEntry in interfaceProxy.Signals) {
00106           EventInfo eventE = (EventInfo) signalEntry.Value;
00107           // This is really cheeky since we need to grab the event as a private field.
00108           FieldInfo eventF = this.type.GetField(eventE.Name,
00109                                                 BindingFlags.NonPublic|
00110                                                 BindingFlags.Instance);
00111 
00112           MethodInfo eventHandler_InvokeMI = eventE.EventHandlerType.GetMethod("Invoke");
00113 
00114           ParameterInfo[] pars = eventHandler_InvokeMI.GetParameters();
00115           parTypes = new Type[pars.Length];
00116           for (int parN = 0; parN < pars.Length; parN++) {
00117             parTypes[parN] = pars[parN].ParameterType;
00118             LocalBuilder parmL = generator.DeclareLocal(parTypes[parN]);
00119             parmL.SetLocalSymInfo(pars[parN].Name);
00120           }
00121           
00122           Label skip = generator.DefineLabel();      
00123           //generator.EmitWriteLine("  if (SelectedIndexChanged != null) {");
00124           generator.Emit(OpCodes.Ldarg_0);
00125           generator.Emit(OpCodes.Ldfld, eventF);
00126           generator.Emit(OpCodes.Ldnull);
00127           generator.EmitCall(OpCodes.Call, MulticastDelegate_opInequalityMI, null);
00128           generator.Emit(OpCodes.Brfalse, skip);
00129           
00130           //generator.EmitWriteLine("    if (signal.Key == 'la i')");
00131           generator.Emit(OpCodes.Ldarg_1);
00132           generator.EmitCall(OpCodes.Callvirt, Message_KeyMI, null);
00133           generator.Emit(OpCodes.Ldstr, eventE.Name + " " + InterfaceProxy.GetSignature(eventHandler_InvokeMI));
00134           generator.EmitCall(OpCodes.Call, String_opEqualityMI, null);
00135           generator.Emit(OpCodes.Brfalse, skip);
00136 
00137           //generator.EmitWriteLine("IEnumerator enumerator = signal.Arguments.GetEnumerator()");
00138           generator.Emit(OpCodes.Ldarg_1);
00139           generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
00140           generator.EmitCall(OpCodes.Callvirt, Arguments_GetEnumeratorMI, null);
00141           generator.Emit(OpCodes.Stloc_0);
00142           
00143           for (int parN = 0; parN < pars.Length; parN++) {
00144             ParameterInfo par = pars[parN];
00145             if (!par.IsOut) {
00146               EmitSignalIn(generator, par.ParameterType, parN + localOffset, serviceF);
00147             }
00148           }
00149           
00150           //generator.EmitWriteLine("    SelectedIndexChanged(selectedIndex)");
00151           generator.Emit(OpCodes.Ldarg_0);
00152           generator.Emit(OpCodes.Ldfld, eventF);
00153           for (int parN = 0; parN < pars.Length; parN++) {
00154             generator.Emit(OpCodes.Ldloc_S, parN + localOffset);
00155           }
00156           
00157           generator.EmitCall(OpCodes.Callvirt, eventHandler_InvokeMI, null);
00158           
00159           generator.MarkLabel(skip);
00160           //generator.EmitWriteLine("  }");
00161           
00162           localOffset += pars.Length;
00163         }
00164       }
00165 
00166       generator.MarkLabel(wrongPath);
00167       //generator.EmitWriteLine("}");
00168 
00169       //generator.EmitWriteLine("return");
00170       generator.Emit(OpCodes.Ret);
00171 
00172       return methodBuilder;
00173     }
00174     
00175     private void BuildSignalHandler(EventInfo eventE, 
00176                                     InterfaceProxy interfaceProxy,
00177                                     ref TypeBuilder typeB, 
00178                                     FieldInfo serviceF,
00179                                     FieldInfo pathF)
00180     {
00181       MethodInfo eventHandler_InvokeMI = eventE.EventHandlerType.GetMethod("Invoke");
00182       ParameterInfo[] pars = eventHandler_InvokeMI.GetParameters();
00183       Type[] parTypes = new Type[pars.Length];
00184       for (int parN = 0; parN < pars.Length; parN++) {
00185         parTypes[parN] = pars[parN].ParameterType;
00186       }
00187 
00188       // Generate the code
00189       MethodBuilder methodBuilder = typeB.DefineMethod("Proxy_" + eventE.Name, 
00190                                                        MethodAttributes.Public |
00191                                                        MethodAttributes.HideBySig |
00192                                                        MethodAttributes.Virtual, 
00193                                                        typeof(void),
00194                                                        parTypes);
00195       ILGenerator generator = methodBuilder.GetILGenerator();
00196 
00197       for (int parN = 0; parN < pars.Length; parN++) {
00198         methodBuilder.DefineParameter(parN + 1, pars[parN].Attributes, pars[parN].Name);
00199       }
00200 
00201       // Generate the locals
00202       LocalBuilder methodCallL = generator.DeclareLocal(typeof(MethodCall));
00203       methodCallL.SetLocalSymInfo("signal");
00204 
00205       //generator.EmitWriteLine("Signal signal = new Signal(...)");
00206       generator.Emit(OpCodes.Ldsfld, serviceF);
00207       generator.Emit(OpCodes.Ldarg_0);
00208       generator.Emit(OpCodes.Ldfld, pathF);
00209       generator.Emit(OpCodes.Ldstr, interfaceProxy.InterfaceName);
00210       generator.Emit(OpCodes.Ldstr, eventE.Name);
00211       generator.Emit(OpCodes.Newobj, Signal_C);
00212       generator.Emit(OpCodes.Stloc_0);
00213 
00214       //generator.EmitWriteLine("signal.Arguments.InitAppending()");
00215       generator.Emit(OpCodes.Ldloc_0);
00216       generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
00217       generator.EmitCall(OpCodes.Callvirt, Arguments_InitAppendingMI, null);
00218 
00219       for (int parN = 0; parN < pars.Length; parN++) {
00220         ParameterInfo par = pars[parN];
00221         if (!par.IsOut) {
00222           EmitIn(generator, par.ParameterType, parN, serviceF);
00223         }
00224       }
00225       
00226       //generator.EmitWriteLine("signal.Send()");
00227       generator.Emit(OpCodes.Ldloc_0);
00228       generator.EmitCall(OpCodes.Callvirt, Message_SendMI, null); 
00229 
00230       //generator.EmitWriteLine("signal.Dispose()");
00231       generator.Emit(OpCodes.Ldloc_0);
00232       generator.EmitCall(OpCodes.Callvirt, Message_DisposeMI, null);
00233 
00234       //generator.EmitWriteLine("return");
00235       generator.Emit(OpCodes.Ret);
00236     }
00237 
00238     private void BuildMethod(MethodInfo method, 
00239                              InterfaceProxy interfaceProxy,
00240                              ref TypeBuilder typeB, 
00241                              FieldInfo serviceF,
00242                              FieldInfo pathF)
00243     {
00244       ParameterInfo[] pars = method.GetParameters();
00245       Type[] parTypes = new Type[pars.Length];
00246       for (int parN = 0; parN < pars.Length; parN++) {
00247         parTypes[parN] = pars[parN].ParameterType;
00248       }
00249 
00250       // Generate the code
00251       MethodBuilder methodBuilder = typeB.DefineMethod(method.Name, 
00252                                                        MethodAttributes.Public |
00253                                                        MethodAttributes.HideBySig |
00254                                                        MethodAttributes.Virtual, 
00255                                                        method.ReturnType, 
00256                                                        parTypes);
00257       ILGenerator generator = methodBuilder.GetILGenerator();
00258 
00259       for (int parN = 0; parN < pars.Length; parN++) {
00260         methodBuilder.DefineParameter(parN + 1, pars[parN].Attributes, pars[parN].Name);
00261       }
00262 
00263       // Generate the locals
00264       LocalBuilder methodCallL = generator.DeclareLocal(typeof(MethodCall));
00265       methodCallL.SetLocalSymInfo("methodCall");
00266       LocalBuilder replyL = generator.DeclareLocal(typeof(MethodReturn));
00267       replyL.SetLocalSymInfo("reply");
00268       LocalBuilder enumeratorL = generator.DeclareLocal(typeof(System.Collections.IEnumerator));
00269       enumeratorL.SetLocalSymInfo("enumerator");
00270 
00271       if (method.ReturnType != typeof(void)) {
00272         LocalBuilder retvalL = generator.DeclareLocal(method.ReturnType);
00273         retvalL.SetLocalSymInfo("retval");
00274       }
00275 
00276       //generator.EmitWriteLine("MethodCall methodCall = new MethodCall(...)");
00277       generator.Emit(OpCodes.Ldsfld, serviceF);
00278       generator.Emit(OpCodes.Ldarg_0);
00279       generator.Emit(OpCodes.Ldfld, pathF);
00280       generator.Emit(OpCodes.Ldstr, interfaceProxy.InterfaceName);
00281       generator.Emit(OpCodes.Ldstr, method.Name);
00282       generator.Emit(OpCodes.Newobj, MethodCall_C);
00283       generator.Emit(OpCodes.Stloc_0);
00284 
00285       //generator.EmitWriteLine("methodCall.Arguments.InitAppending()");
00286       generator.Emit(OpCodes.Ldloc_0);
00287       generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
00288       generator.EmitCall(OpCodes.Callvirt, Arguments_InitAppendingMI, null);
00289 
00290       for (int parN = 0; parN < pars.Length; parN++) {
00291         ParameterInfo par = pars[parN];
00292         if (!par.IsOut) {
00293           EmitIn(generator, par.ParameterType, parN, serviceF);
00294         }
00295       }
00296       
00297       //generator.EmitWriteLine("MethodReturn reply = methodCall.SendWithReplyAndBlock()");
00298       generator.Emit(OpCodes.Ldloc_0);
00299       generator.EmitCall(OpCodes.Callvirt, Message_SendWithReplyAndBlockMI, null);      
00300       generator.Emit(OpCodes.Stloc_1);
00301 
00302       //generator.EmitWriteLine("IEnumerator enumeartor = reply.Arguments.GetEnumerator()");
00303       generator.Emit(OpCodes.Ldloc_1);
00304       generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
00305       generator.EmitCall(OpCodes.Callvirt, Arguments_GetEnumeratorMI, null);
00306       generator.Emit(OpCodes.Stloc_2);
00307 
00308       // handle the return value
00309       if (method.ReturnType != typeof(void)) {
00310         EmitOut(generator, method.ReturnType, 0);
00311       }
00312 
00313       for (int parN = 0; parN < pars.Length; parN++) {
00314         ParameterInfo par = pars[parN];
00315         if (par.IsOut || par.ParameterType.ToString().EndsWith("&")) {
00316           EmitOut(generator, par.ParameterType, parN);
00317         }
00318       }
00319 
00320       // Clean up after ourselves
00321       //generator.EmitWriteLine("methodCall.Dispose()");
00322       generator.Emit(OpCodes.Ldloc_0);
00323       generator.EmitCall(OpCodes.Callvirt, Message_DisposeMI, null);
00324 
00325       //generator.EmitWriteLine("reply.Dispose()");
00326       generator.Emit(OpCodes.Ldloc_1);
00327       generator.EmitCall(OpCodes.Callvirt, Message_DisposeMI, null);
00328 
00329       if (method.ReturnType != typeof(void)) {
00330         generator.Emit(OpCodes.Ldloc_3);
00331       }
00332       
00333       generator.Emit(OpCodes.Ret);
00334 
00335       // Generate the method
00336       typeB.DefineMethodOverride(methodBuilder, method);
00337     }
00338 
00339     private void EmitSignalIn(ILGenerator generator, Type parType, int parN, FieldInfo serviceF)
00340     {
00341         //generator.EmitWriteLine("enumerator.MoveNext()");
00342         generator.Emit(OpCodes.Ldloc_0);
00343         generator.EmitCall(OpCodes.Callvirt, IEnumerator_MoveNextMI, null);
00344         
00345         Type outParType = Arguments.MatchType(parType);
00346         //generator.EmitWriteLine("int selectedIndex = (int) ((DBusType.IDBusType) enumerator.Current).Get(typeof(int))");
00347         generator.Emit(OpCodes.Pop);
00348         generator.Emit(OpCodes.Ldloc_0);
00349         generator.EmitCall(OpCodes.Callvirt, IEnumerator_CurrentMI, null);
00350         generator.Emit(OpCodes.Castclass, typeof(DBusType.IDBusType));
00351         generator.Emit(OpCodes.Ldtoken, parType);
00352         generator.EmitCall(OpCodes.Call, Type_GetTypeFromHandleMI, null);
00353         generator.EmitCall(OpCodes.Callvirt, IDBusType_GetMI, null);
00354         // Call the DBusType EmitMarshalOut to make it emit itself
00355         object[] pars = new object[] {generator, parType, true};
00356         outParType.InvokeMember("EmitMarshalOut", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, pars, null);
00357         generator.Emit(OpCodes.Stloc_S, parN);
00358     }
00359     
00360 
00361     private void EmitIn(ILGenerator generator, Type parType, int parN, FieldInfo serviceF)
00362     {
00363       Type inParType = Arguments.MatchType(parType);
00364       //generator.EmitWriteLine("methodCall.Arguments.Append(...)");
00365       generator.Emit(OpCodes.Ldloc_0);
00366       generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
00367       generator.Emit(OpCodes.Ldarg_S, parN + 1);
00368 
00369       // Call the DBusType EmitMarshalIn to make it emit itself
00370       object[] pars = new object[] {generator, parType};
00371       inParType.InvokeMember("EmitMarshalIn", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, pars, null);
00372 
00373       generator.Emit(OpCodes.Ldsfld, serviceF);
00374       generator.Emit(OpCodes.Newobj, Arguments.GetDBusTypeConstructor(inParType, parType));
00375       generator.EmitCall(OpCodes.Callvirt, Arguments_AppendMI, null);
00376     }
00377 
00378     private void EmitOut(ILGenerator generator, Type parType, int parN)
00379     {
00380       Type outParType = Arguments.MatchType(parType);
00381       //generator.EmitWriteLine("enumerator.MoveNext()");
00382       generator.Emit(OpCodes.Ldloc_2);
00383       generator.EmitCall(OpCodes.Callvirt, IEnumerator_MoveNextMI, null);
00384 
00385       //generator.EmitWriteLine("return (" + parType + ") ((DBusType.IDBusType) enumerator.Current).Get(typeof(" + parType + "))");
00386       generator.Emit(OpCodes.Pop);
00387       if (parN > 0) {
00388         generator.Emit(OpCodes.Ldarg_S, parN + 1);
00389       }
00390       
00391       generator.Emit(OpCodes.Ldloc_2);
00392       generator.EmitCall(OpCodes.Callvirt, IEnumerator_CurrentMI, null);
00393       generator.Emit(OpCodes.Castclass, typeof(DBusType.IDBusType));
00394       generator.Emit(OpCodes.Ldtoken, parType);
00395       generator.EmitCall(OpCodes.Call, Type_GetTypeFromHandleMI, null);
00396       generator.EmitCall(OpCodes.Callvirt, IDBusType_GetMI, null);
00397 
00398       // Call the DBusType EmitMarshalOut to make it emit itself
00399       object[] pars = new object[] {generator, parType, parN == 0};
00400       outParType.InvokeMember("EmitMarshalOut", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, pars, null);
00401       
00402       if (parN == 0) {
00403         generator.Emit(OpCodes.Stloc_3);
00404       }
00405     }
00406     
00407     public void BuildConstructor(ref TypeBuilder typeB, FieldInfo serviceF, FieldInfo pathF, MethodInfo signalCalledMI, FieldInfo deleF)
00408     {
00409       Type[] pars = {typeof(Service), typeof(string)};
00410       ConstructorBuilder constructor = typeB.DefineConstructor(MethodAttributes.RTSpecialName | 
00411                                                                MethodAttributes.Public,
00412                                                                CallingConventions.Standard, pars);
00413 
00414       ILGenerator generator = constructor.GetILGenerator();
00415 
00416       LocalBuilder handlerL = generator.DeclareLocal (typeof (Service.SignalCalledHandler));
00417       handlerL.SetLocalSymInfo ("handler");
00418 
00419       generator.Emit(OpCodes.Ldarg_0);
00420       generator.Emit(OpCodes.Call, this.introspector.Constructor);
00421       //generator.EmitWriteLine("service = myService");
00422       generator.Emit(OpCodes.Ldarg_1);
00423       generator.Emit(OpCodes.Stsfld, serviceF);
00424       //generator.EmitWriteLine("this.pathName = pathName");
00425       generator.Emit(OpCodes.Ldarg_0);
00426       generator.Emit(OpCodes.Ldarg_2);
00427       generator.Emit(OpCodes.Stfld, pathF);
00428 
00429       //generator.EmitWriteLine("handler = new Service.SignalCalledHandler(Service_SignalCalled)");      
00430       generator.Emit(OpCodes.Ldarg_1);
00431       generator.Emit(OpCodes.Ldarg_0);
00432       generator.Emit(OpCodes.Ldftn, signalCalledMI);
00433       generator.Emit(OpCodes.Newobj, Service_SignalCalledHandlerC);
00434       generator.Emit(OpCodes.Stloc_0);
00435 
00436       //generator.EmitWriteLine("this.delegate_created = handler");
00437       generator.Emit(OpCodes.Ldarg_0);
00438       generator.Emit(OpCodes.Ldloc_0);
00439       generator.Emit(OpCodes.Stfld, deleF);
00440 
00441       //generator.EmitWriteLine("myService.SignalCalled += handler");
00442       generator.Emit(OpCodes.Ldloc_0);
00443       generator.EmitCall(OpCodes.Callvirt, Service_AddSignalCalledMI, null);
00444 
00445       //generator.EmitWriteLine("return");
00446       generator.Emit(OpCodes.Ret);
00447     }
00448 
00449     public void BuildSignalConstructor(ref TypeBuilder typeB, FieldInfo serviceF, FieldInfo pathF)
00450     {
00451       Type[] pars = {typeof(Service), typeof(string)};
00452       ConstructorBuilder constructor = typeB.DefineConstructor(MethodAttributes.RTSpecialName | 
00453                                                                MethodAttributes.Public,
00454                                                                CallingConventions.Standard, pars);
00455 
00456       ILGenerator generator = constructor.GetILGenerator();
00457       generator.Emit(OpCodes.Ldarg_0);
00458       generator.Emit(OpCodes.Call, this.introspector.Constructor);
00459       //generator.EmitWriteLine("service = myService");
00460       generator.Emit(OpCodes.Ldarg_1);
00461       generator.Emit(OpCodes.Stsfld, serviceF);
00462       //generator.EmitWriteLine("this.pathName = pathName");
00463       generator.Emit(OpCodes.Ldarg_0);
00464       generator.Emit(OpCodes.Ldarg_2);
00465       generator.Emit(OpCodes.Stfld, pathF);
00466       
00467       //generator.EmitWriteLine("return");
00468       generator.Emit(OpCodes.Ret);
00469     }
00470     
00471     public void BuildFinalizer (TypeBuilder tb, FieldInfo serviceF, FieldInfo deleF)
00472     {
00473        // Note that this is a *HORRIBLE* example of how to build a finalizer
00474        // It doesn't use the try/finally to chain to Object::Finalize. However,
00475        // because that is always going to be a nop, lets just ignore that here.
00476        // If you are trying to find the right code, look at what mcs does ;-).
00477 
00478        MethodBuilder mb = tb.DefineMethod("Finalize",
00479                                           MethodAttributes.Family |
00480                                           MethodAttributes.HideBySig |
00481                                           MethodAttributes.Virtual, 
00482                                           typeof (void), 
00483                                           new Type [0]);
00484        ILGenerator generator = mb.GetILGenerator();
00485 
00486        //generator.EmitWriteLine("this.service.SignalCalled -= this.delegate_created");
00487        generator.Emit (OpCodes.Ldarg_0);
00488        generator.Emit (OpCodes.Ldfld, serviceF);
00489        generator.Emit (OpCodes.Ldarg_0);
00490        generator.Emit (OpCodes.Ldfld, deleF);
00491        generator.EmitCall (OpCodes.Callvirt, Service_RemoveSignalCalledMI, null);
00492        generator.Emit (OpCodes.Ret);
00493     }
00494     
00495     public object GetSignalProxy()
00496     {
00497       Type proxyType = Service.ProxyAssembly.GetType(ObjectName + ".SignalProxy");
00498 
00499       if (proxyType == null) {
00500         // Build the type
00501         TypeBuilder typeB = Service.Module.DefineType(ObjectName + ".SignalProxy", 
00502                                                       TypeAttributes.Public, 
00503                                                       this.type);
00504         
00505         FieldBuilder serviceF = typeB.DefineField("service", 
00506                                                   typeof(Service), 
00507                                                   FieldAttributes.Private | 
00508                                                   FieldAttributes.Static);
00509         FieldBuilder pathF = typeB.DefineField("pathName", 
00510                                                typeof(string), 
00511                                                FieldAttributes.Private);
00512 
00513         BuildSignalConstructor(ref typeB, serviceF, pathF);
00514         
00515         // Build the signal handlers
00516         foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {
00517           InterfaceProxy interfaceProxy = (InterfaceProxy) interfaceEntry.Value;
00518           foreach (DictionaryEntry signalEntry in interfaceProxy.Signals) {
00519             EventInfo eventE = (EventInfo) signalEntry.Value;
00520             BuildSignalHandler(eventE, interfaceProxy, ref typeB, serviceF, pathF);
00521           }
00522         }
00523         
00524         proxyType = typeB.CreateType();
00525       
00526         // Uncomment the following line to produce a DLL of the
00527         // constructed assembly which can then be examined using
00528         // monodis. Note that in order for this to work you should copy
00529         // the client assembly as a dll file so that monodis can pick it
00530         // up.
00531         //Service.ProxyAssembly.Save("proxy.dll");
00532       }
00533 
00534       Type [] parTypes = new Type[] {typeof(Service), typeof(string)};
00535       object [] pars = new object[] {Service, pathName};
00536       
00537       ConstructorInfo constructor = proxyType.GetConstructor(parTypes);
00538       object instance = constructor.Invoke(pars);
00539       return instance;
00540     }
00541       
00542     
00543     public object GetProxy() 
00544     { 
00545       Type proxyType = Service.ProxyAssembly.GetType(ObjectName + ".Proxy");
00546       
00547       if (proxyType == null) {
00548         // Build the type
00549         TypeBuilder typeB = Service.Module.DefineType(ObjectName + ".Proxy", TypeAttributes.Public, this.type);
00550         
00551         FieldBuilder serviceF = typeB.DefineField("service", 
00552                                                   typeof(Service), 
00553                                                   FieldAttributes.Private | 
00554                                                   FieldAttributes.Static);
00555         FieldBuilder pathF = typeB.DefineField("pathName", 
00556                                                typeof(string), 
00557                                                FieldAttributes.Private);
00558         FieldBuilder deleF = typeB.DefineField("delegate_created", 
00559                                                typeof(Service.SignalCalledHandler), 
00560                                                FieldAttributes.Private);
00561         BuildFinalizer (typeB, serviceF, deleF);
00562         
00563         MethodInfo signalCalledMI = BuildSignalCalled(ref typeB, serviceF, pathF);
00564         BuildConstructor(ref typeB, serviceF, pathF, signalCalledMI, deleF);
00565         
00566         // Build the methods
00567         foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {
00568           InterfaceProxy interfaceProxy = (InterfaceProxy) interfaceEntry.Value;
00569           foreach (DictionaryEntry methodEntry in interfaceProxy.Methods) {
00570             MethodInfo method = (MethodInfo) methodEntry.Value;
00571             BuildMethod(method, interfaceProxy, ref typeB, serviceF, pathF);
00572           }
00573         }
00574         
00575         proxyType = typeB.CreateType();
00576       
00577         // Uncomment the following line to produce a DLL of the
00578         // constructed assembly which can then be examined using
00579         // monodis. Note that in order for this to work you should copy
00580         // the client assembly as a dll file so that monodis can pick it
00581         // up.
00582         //Service.ProxyAssembly.Save(Service.Name + ".proxy.dll");
00583       }
00584 
00585       Type [] parTypes = new Type[] {typeof(Service), typeof(string)};
00586       object [] pars = new object[] {Service, pathName};
00587       
00588       ConstructorInfo constructor = proxyType.GetConstructor(parTypes);
00589       object instance = constructor.Invoke(pars);
00590       return instance;
00591     }
00592     
00593     private Service Service
00594     {
00595       get {
00596         return this.service;
00597       }
00598     }
00599 
00600     private string ObjectName
00601     {
00602       get {
00603         return this.introspector.ToString();
00604       }
00605     }
00606   }
00607 }
00608 

Generated on Tue Sep 13 01:28:08 2005 for D-BUS by  doxygen 1.4.4