2004-03-23 12:10:32 +00:00
|
|
|
namespace DBus
|
|
|
|
|
{
|
|
|
|
|
using System;
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.Collections;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Reflection.Emit;
|
|
|
|
|
|
|
|
|
|
internal class ProxyBuilder
|
|
|
|
|
{
|
|
|
|
|
private Service service= null;
|
|
|
|
|
private string pathName = null;
|
|
|
|
|
private Type type = null;
|
|
|
|
|
private Introspector introspector = null;
|
|
|
|
|
|
|
|
|
|
private static MethodInfo Service_NameMI = typeof(Service).GetMethod("get_Name",
|
|
|
|
|
new Type[0]);
|
|
|
|
|
private static MethodInfo Service_ConnectionMI = typeof(Service).GetMethod("get_Connection",
|
|
|
|
|
new Type[0]);
|
2004-03-26 15:25:59 +00:00
|
|
|
private static MethodInfo Service_AddSignalCalledMI = typeof(Service).GetMethod("add_SignalCalled",
|
|
|
|
|
new Type[] {typeof(Service.SignalCalledHandler)});
|
2005-03-13 01:13:04 +00:00
|
|
|
private static MethodInfo Service_RemoveSignalCalledMI = typeof(Service).GetMethod("remove_SignalCalled",
|
|
|
|
|
new Type[] {typeof(Service.SignalCalledHandler)});
|
2004-03-26 15:25:59 +00:00
|
|
|
private static MethodInfo Signal_PathNameMI = typeof(Signal).GetMethod("get_PathName",
|
|
|
|
|
new Type[0]);
|
2004-03-23 12:10:32 +00:00
|
|
|
private static MethodInfo Message_ArgumentsMI = typeof(Message).GetMethod("get_Arguments",
|
|
|
|
|
new Type[0]);
|
2004-03-26 15:25:59 +00:00
|
|
|
private static MethodInfo Message_KeyMI = typeof(Message).GetMethod("get_Key",
|
|
|
|
|
new Type[0]);
|
2004-03-23 12:10:32 +00:00
|
|
|
private static MethodInfo Arguments_InitAppendingMI = typeof(Arguments).GetMethod("InitAppending",
|
|
|
|
|
new Type[0]);
|
|
|
|
|
private static MethodInfo Arguments_AppendMI = typeof(Arguments).GetMethod("Append",
|
|
|
|
|
new Type[] {typeof(DBusType.IDBusType)});
|
|
|
|
|
private static MethodInfo Message_SendWithReplyAndBlockMI = typeof(Message).GetMethod("SendWithReplyAndBlock",
|
|
|
|
|
new Type[0]);
|
2004-03-26 15:25:59 +00:00
|
|
|
private static MethodInfo Message_SendMI = typeof(Message).GetMethod("Send",
|
|
|
|
|
new Type[0]);
|
2005-03-09 04:36:15 +00:00
|
|
|
private static MethodInfo Message_DisposeMI = typeof(Message).GetMethod("Dispose",
|
|
|
|
|
new Type[0]);
|
2004-03-23 12:10:32 +00:00
|
|
|
private static MethodInfo Arguments_GetEnumeratorMI = typeof(Arguments).GetMethod("GetEnumerator",
|
|
|
|
|
new Type[0]);
|
|
|
|
|
private static MethodInfo IEnumerator_MoveNextMI = typeof(System.Collections.IEnumerator).GetMethod("MoveNext",
|
|
|
|
|
new Type[0]);
|
|
|
|
|
private static MethodInfo IEnumerator_CurrentMI = typeof(System.Collections.IEnumerator).GetMethod("get_Current",
|
|
|
|
|
new Type[0]);
|
|
|
|
|
private static MethodInfo Type_GetTypeFromHandleMI = typeof(System.Type).GetMethod("GetTypeFromHandle",
|
|
|
|
|
new Type[] {typeof(System.RuntimeTypeHandle)});
|
|
|
|
|
private static MethodInfo IDBusType_GetMI = typeof(DBusType.IDBusType).GetMethod("Get",
|
|
|
|
|
new Type[] {typeof(System.Type)});
|
|
|
|
|
private static ConstructorInfo MethodCall_C = typeof(MethodCall).GetConstructor(new Type[] {typeof(Service),
|
|
|
|
|
typeof(string),
|
|
|
|
|
typeof(string),
|
|
|
|
|
typeof(string)});
|
2004-03-26 15:25:59 +00:00
|
|
|
private static ConstructorInfo Signal_C = typeof(Signal).GetConstructor(new Type[] {typeof(Service),
|
|
|
|
|
typeof(string),
|
|
|
|
|
typeof(string),
|
|
|
|
|
typeof(string)});
|
|
|
|
|
private static ConstructorInfo Service_SignalCalledHandlerC = typeof(Service.SignalCalledHandler).GetConstructor(new Type[] {typeof(object),
|
|
|
|
|
typeof(System.IntPtr)});
|
|
|
|
|
private static MethodInfo String_opEqualityMI = typeof(System.String).GetMethod("op_Equality",
|
|
|
|
|
new Type[] {typeof(string),
|
|
|
|
|
typeof(string)});
|
|
|
|
|
private static MethodInfo MulticastDelegate_opInequalityMI = typeof(System.MulticastDelegate).GetMethod("op_Inequality",
|
|
|
|
|
new Type[] {typeof(System.MulticastDelegate),
|
|
|
|
|
typeof(System.MulticastDelegate)});
|
2004-03-23 12:10:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
public ProxyBuilder(Service service, Type type, string pathName)
|
|
|
|
|
{
|
|
|
|
|
this.service = service;
|
|
|
|
|
this.pathName = pathName;
|
|
|
|
|
this.type = type;
|
2004-03-23 18:07:48 +00:00
|
|
|
this.introspector = Introspector.GetIntrospector(type);
|
2004-03-23 12:10:32 +00:00
|
|
|
}
|
|
|
|
|
|
2004-03-26 15:25:59 +00:00
|
|
|
private MethodInfo BuildSignalCalled(ref TypeBuilder typeB, FieldInfo serviceF, FieldInfo pathF)
|
|
|
|
|
{
|
|
|
|
|
Type[] parTypes = {typeof(Signal)};
|
|
|
|
|
MethodBuilder methodBuilder = typeB.DefineMethod("Service_SignalCalled",
|
|
|
|
|
MethodAttributes.Private |
|
|
|
|
|
MethodAttributes.HideBySig,
|
|
|
|
|
typeof(void),
|
|
|
|
|
parTypes);
|
|
|
|
|
|
|
|
|
|
ILGenerator generator = methodBuilder.GetILGenerator();
|
|
|
|
|
|
|
|
|
|
LocalBuilder enumeratorL = generator.DeclareLocal(typeof(System.Collections.IEnumerator));
|
|
|
|
|
enumeratorL.SetLocalSymInfo("enumerator");
|
|
|
|
|
|
|
|
|
|
Label wrongPath = generator.DefineLabel();
|
|
|
|
|
//generator.EmitWriteLine("if (signal.PathName == pathName) {");
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_1);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, Signal_PathNameMI, null);
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Ldfld, pathF);
|
|
|
|
|
generator.EmitCall(OpCodes.Call, String_opEqualityMI, null);
|
|
|
|
|
generator.Emit(OpCodes.Brfalse, wrongPath);
|
|
|
|
|
|
|
|
|
|
int localOffset = 1;
|
|
|
|
|
|
|
|
|
|
foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {
|
|
|
|
|
InterfaceProxy interfaceProxy = (InterfaceProxy) interfaceEntry.Value;
|
|
|
|
|
foreach (DictionaryEntry signalEntry in interfaceProxy.Signals) {
|
|
|
|
|
EventInfo eventE = (EventInfo) signalEntry.Value;
|
|
|
|
|
// This is really cheeky since we need to grab the event as a private field.
|
|
|
|
|
FieldInfo eventF = this.type.GetField(eventE.Name,
|
|
|
|
|
BindingFlags.NonPublic|
|
|
|
|
|
BindingFlags.Instance);
|
|
|
|
|
|
|
|
|
|
MethodInfo eventHandler_InvokeMI = eventE.EventHandlerType.GetMethod("Invoke");
|
|
|
|
|
|
|
|
|
|
ParameterInfo[] pars = eventHandler_InvokeMI.GetParameters();
|
|
|
|
|
parTypes = new Type[pars.Length];
|
|
|
|
|
for (int parN = 0; parN < pars.Length; parN++) {
|
|
|
|
|
parTypes[parN] = pars[parN].ParameterType;
|
|
|
|
|
LocalBuilder parmL = generator.DeclareLocal(parTypes[parN]);
|
|
|
|
|
parmL.SetLocalSymInfo(pars[parN].Name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Label skip = generator.DefineLabel();
|
|
|
|
|
//generator.EmitWriteLine(" if (SelectedIndexChanged != null) {");
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Ldfld, eventF);
|
|
|
|
|
generator.Emit(OpCodes.Ldnull);
|
|
|
|
|
generator.EmitCall(OpCodes.Call, MulticastDelegate_opInequalityMI, null);
|
|
|
|
|
generator.Emit(OpCodes.Brfalse, skip);
|
|
|
|
|
|
|
|
|
|
//generator.EmitWriteLine(" if (signal.Key == 'la i')");
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_1);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, Message_KeyMI, null);
|
|
|
|
|
generator.Emit(OpCodes.Ldstr, eventE.Name + " " + InterfaceProxy.GetSignature(eventHandler_InvokeMI));
|
|
|
|
|
generator.EmitCall(OpCodes.Call, String_opEqualityMI, null);
|
|
|
|
|
generator.Emit(OpCodes.Brfalse, skip);
|
|
|
|
|
|
|
|
|
|
//generator.EmitWriteLine("IEnumerator enumerator = signal.Arguments.GetEnumerator()");
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_1);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, Arguments_GetEnumeratorMI, null);
|
|
|
|
|
generator.Emit(OpCodes.Stloc_0);
|
|
|
|
|
|
|
|
|
|
for (int parN = 0; parN < pars.Length; parN++) {
|
|
|
|
|
ParameterInfo par = pars[parN];
|
|
|
|
|
if (!par.IsOut) {
|
|
|
|
|
EmitSignalIn(generator, par.ParameterType, parN + localOffset, serviceF);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//generator.EmitWriteLine(" SelectedIndexChanged(selectedIndex)");
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Ldfld, eventF);
|
|
|
|
|
for (int parN = 0; parN < pars.Length; parN++) {
|
|
|
|
|
generator.Emit(OpCodes.Ldloc_S, parN + localOffset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, eventHandler_InvokeMI, null);
|
|
|
|
|
|
|
|
|
|
generator.MarkLabel(skip);
|
|
|
|
|
//generator.EmitWriteLine(" }");
|
|
|
|
|
|
|
|
|
|
localOffset += pars.Length;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
generator.MarkLabel(wrongPath);
|
|
|
|
|
//generator.EmitWriteLine("}");
|
|
|
|
|
|
|
|
|
|
//generator.EmitWriteLine("return");
|
|
|
|
|
generator.Emit(OpCodes.Ret);
|
|
|
|
|
|
|
|
|
|
return methodBuilder;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void BuildSignalHandler(EventInfo eventE,
|
|
|
|
|
InterfaceProxy interfaceProxy,
|
|
|
|
|
ref TypeBuilder typeB,
|
|
|
|
|
FieldInfo serviceF,
|
|
|
|
|
FieldInfo pathF)
|
|
|
|
|
{
|
|
|
|
|
MethodInfo eventHandler_InvokeMI = eventE.EventHandlerType.GetMethod("Invoke");
|
|
|
|
|
ParameterInfo[] pars = eventHandler_InvokeMI.GetParameters();
|
|
|
|
|
Type[] parTypes = new Type[pars.Length];
|
|
|
|
|
for (int parN = 0; parN < pars.Length; parN++) {
|
|
|
|
|
parTypes[parN] = pars[parN].ParameterType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Generate the code
|
|
|
|
|
MethodBuilder methodBuilder = typeB.DefineMethod("Proxy_" + eventE.Name,
|
|
|
|
|
MethodAttributes.Public |
|
|
|
|
|
MethodAttributes.HideBySig |
|
|
|
|
|
MethodAttributes.Virtual,
|
|
|
|
|
typeof(void),
|
|
|
|
|
parTypes);
|
|
|
|
|
ILGenerator generator = methodBuilder.GetILGenerator();
|
|
|
|
|
|
|
|
|
|
for (int parN = 0; parN < pars.Length; parN++) {
|
|
|
|
|
methodBuilder.DefineParameter(parN + 1, pars[parN].Attributes, pars[parN].Name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Generate the locals
|
|
|
|
|
LocalBuilder methodCallL = generator.DeclareLocal(typeof(MethodCall));
|
|
|
|
|
methodCallL.SetLocalSymInfo("signal");
|
|
|
|
|
|
|
|
|
|
//generator.EmitWriteLine("Signal signal = new Signal(...)");
|
|
|
|
|
generator.Emit(OpCodes.Ldsfld, serviceF);
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Ldfld, pathF);
|
|
|
|
|
generator.Emit(OpCodes.Ldstr, interfaceProxy.InterfaceName);
|
|
|
|
|
generator.Emit(OpCodes.Ldstr, eventE.Name);
|
|
|
|
|
generator.Emit(OpCodes.Newobj, Signal_C);
|
|
|
|
|
generator.Emit(OpCodes.Stloc_0);
|
|
|
|
|
|
|
|
|
|
//generator.EmitWriteLine("signal.Arguments.InitAppending()");
|
|
|
|
|
generator.Emit(OpCodes.Ldloc_0);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, Arguments_InitAppendingMI, null);
|
|
|
|
|
|
|
|
|
|
for (int parN = 0; parN < pars.Length; parN++) {
|
|
|
|
|
ParameterInfo par = pars[parN];
|
|
|
|
|
if (!par.IsOut) {
|
|
|
|
|
EmitIn(generator, par.ParameterType, parN, serviceF);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//generator.EmitWriteLine("signal.Send()");
|
|
|
|
|
generator.Emit(OpCodes.Ldloc_0);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, Message_SendMI, null);
|
|
|
|
|
|
2005-03-09 04:36:15 +00:00
|
|
|
//generator.EmitWriteLine("signal.Dispose()");
|
|
|
|
|
generator.Emit(OpCodes.Ldloc_0);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, Message_DisposeMI, null);
|
|
|
|
|
|
2004-03-26 15:25:59 +00:00
|
|
|
//generator.EmitWriteLine("return");
|
|
|
|
|
generator.Emit(OpCodes.Ret);
|
|
|
|
|
}
|
|
|
|
|
|
2004-03-23 12:10:32 +00:00
|
|
|
private void BuildMethod(MethodInfo method,
|
2004-03-23 18:07:48 +00:00
|
|
|
InterfaceProxy interfaceProxy,
|
2004-03-23 12:10:32 +00:00
|
|
|
ref TypeBuilder typeB,
|
|
|
|
|
FieldInfo serviceF,
|
|
|
|
|
FieldInfo pathF)
|
|
|
|
|
{
|
|
|
|
|
ParameterInfo[] pars = method.GetParameters();
|
|
|
|
|
Type[] parTypes = new Type[pars.Length];
|
|
|
|
|
for (int parN = 0; parN < pars.Length; parN++) {
|
|
|
|
|
parTypes[parN] = pars[parN].ParameterType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Generate the code
|
|
|
|
|
MethodBuilder methodBuilder = typeB.DefineMethod(method.Name,
|
|
|
|
|
MethodAttributes.Public |
|
|
|
|
|
MethodAttributes.HideBySig |
|
|
|
|
|
MethodAttributes.Virtual,
|
|
|
|
|
method.ReturnType,
|
|
|
|
|
parTypes);
|
|
|
|
|
ILGenerator generator = methodBuilder.GetILGenerator();
|
|
|
|
|
|
|
|
|
|
for (int parN = 0; parN < pars.Length; parN++) {
|
|
|
|
|
methodBuilder.DefineParameter(parN + 1, pars[parN].Attributes, pars[parN].Name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Generate the locals
|
|
|
|
|
LocalBuilder methodCallL = generator.DeclareLocal(typeof(MethodCall));
|
|
|
|
|
methodCallL.SetLocalSymInfo("methodCall");
|
|
|
|
|
LocalBuilder replyL = generator.DeclareLocal(typeof(MethodReturn));
|
|
|
|
|
replyL.SetLocalSymInfo("reply");
|
|
|
|
|
LocalBuilder enumeratorL = generator.DeclareLocal(typeof(System.Collections.IEnumerator));
|
|
|
|
|
enumeratorL.SetLocalSymInfo("enumerator");
|
|
|
|
|
|
|
|
|
|
if (method.ReturnType != typeof(void)) {
|
|
|
|
|
LocalBuilder retvalL = generator.DeclareLocal(method.ReturnType);
|
|
|
|
|
retvalL.SetLocalSymInfo("retval");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//generator.EmitWriteLine("MethodCall methodCall = new MethodCall(...)");
|
|
|
|
|
generator.Emit(OpCodes.Ldsfld, serviceF);
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Ldfld, pathF);
|
2004-03-23 18:07:48 +00:00
|
|
|
generator.Emit(OpCodes.Ldstr, interfaceProxy.InterfaceName);
|
2004-03-23 12:10:32 +00:00
|
|
|
generator.Emit(OpCodes.Ldstr, method.Name);
|
|
|
|
|
generator.Emit(OpCodes.Newobj, MethodCall_C);
|
|
|
|
|
generator.Emit(OpCodes.Stloc_0);
|
|
|
|
|
|
|
|
|
|
//generator.EmitWriteLine("methodCall.Arguments.InitAppending()");
|
|
|
|
|
generator.Emit(OpCodes.Ldloc_0);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, Arguments_InitAppendingMI, null);
|
|
|
|
|
|
|
|
|
|
for (int parN = 0; parN < pars.Length; parN++) {
|
|
|
|
|
ParameterInfo par = pars[parN];
|
|
|
|
|
if (!par.IsOut) {
|
2004-03-24 13:15:20 +00:00
|
|
|
EmitIn(generator, par.ParameterType, parN, serviceF);
|
2004-03-23 12:10:32 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//generator.EmitWriteLine("MethodReturn reply = methodCall.SendWithReplyAndBlock()");
|
|
|
|
|
generator.Emit(OpCodes.Ldloc_0);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, Message_SendWithReplyAndBlockMI, null);
|
|
|
|
|
generator.Emit(OpCodes.Stloc_1);
|
|
|
|
|
|
|
|
|
|
//generator.EmitWriteLine("IEnumerator enumeartor = reply.Arguments.GetEnumerator()");
|
|
|
|
|
generator.Emit(OpCodes.Ldloc_1);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, Arguments_GetEnumeratorMI, null);
|
|
|
|
|
generator.Emit(OpCodes.Stloc_2);
|
|
|
|
|
|
|
|
|
|
// handle the return value
|
|
|
|
|
if (method.ReturnType != typeof(void)) {
|
|
|
|
|
EmitOut(generator, method.ReturnType, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int parN = 0; parN < pars.Length; parN++) {
|
|
|
|
|
ParameterInfo par = pars[parN];
|
|
|
|
|
if (par.IsOut || par.ParameterType.ToString().EndsWith("&")) {
|
|
|
|
|
EmitOut(generator, par.ParameterType, parN);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-03-09 04:36:15 +00:00
|
|
|
// Clean up after ourselves
|
|
|
|
|
//generator.EmitWriteLine("methodCall.Dispose()");
|
|
|
|
|
generator.Emit(OpCodes.Ldloc_0);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, Message_DisposeMI, null);
|
|
|
|
|
|
|
|
|
|
//generator.EmitWriteLine("reply.Dispose()");
|
|
|
|
|
generator.Emit(OpCodes.Ldloc_1);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, Message_DisposeMI, null);
|
|
|
|
|
|
2004-03-23 12:10:32 +00:00
|
|
|
if (method.ReturnType != typeof(void)) {
|
|
|
|
|
generator.Emit(OpCodes.Ldloc_3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
generator.Emit(OpCodes.Ret);
|
|
|
|
|
|
|
|
|
|
// Generate the method
|
|
|
|
|
typeB.DefineMethodOverride(methodBuilder, method);
|
|
|
|
|
}
|
|
|
|
|
|
2004-03-26 15:25:59 +00:00
|
|
|
private void EmitSignalIn(ILGenerator generator, Type parType, int parN, FieldInfo serviceF)
|
|
|
|
|
{
|
|
|
|
|
//generator.EmitWriteLine("enumerator.MoveNext()");
|
|
|
|
|
generator.Emit(OpCodes.Ldloc_0);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, IEnumerator_MoveNextMI, null);
|
|
|
|
|
|
|
|
|
|
Type outParType = Arguments.MatchType(parType);
|
|
|
|
|
//generator.EmitWriteLine("int selectedIndex = (int) ((DBusType.IDBusType) enumerator.Current).Get(typeof(int))");
|
|
|
|
|
generator.Emit(OpCodes.Pop);
|
|
|
|
|
generator.Emit(OpCodes.Ldloc_0);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, IEnumerator_CurrentMI, null);
|
|
|
|
|
generator.Emit(OpCodes.Castclass, typeof(DBusType.IDBusType));
|
|
|
|
|
generator.Emit(OpCodes.Ldtoken, parType);
|
|
|
|
|
generator.EmitCall(OpCodes.Call, Type_GetTypeFromHandleMI, null);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, IDBusType_GetMI, null);
|
|
|
|
|
// Call the DBusType EmitMarshalOut to make it emit itself
|
|
|
|
|
object[] pars = new object[] {generator, parType, true};
|
|
|
|
|
outParType.InvokeMember("EmitMarshalOut", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, pars, null);
|
|
|
|
|
generator.Emit(OpCodes.Stloc_S, parN);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-03-24 13:15:20 +00:00
|
|
|
private void EmitIn(ILGenerator generator, Type parType, int parN, FieldInfo serviceF)
|
2004-03-23 12:10:32 +00:00
|
|
|
{
|
|
|
|
|
Type inParType = Arguments.MatchType(parType);
|
|
|
|
|
//generator.EmitWriteLine("methodCall.Arguments.Append(...)");
|
|
|
|
|
generator.Emit(OpCodes.Ldloc_0);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_S, parN + 1);
|
|
|
|
|
|
|
|
|
|
// Call the DBusType EmitMarshalIn to make it emit itself
|
|
|
|
|
object[] pars = new object[] {generator, parType};
|
|
|
|
|
inParType.InvokeMember("EmitMarshalIn", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, pars, null);
|
|
|
|
|
|
2004-03-24 13:15:20 +00:00
|
|
|
generator.Emit(OpCodes.Ldsfld, serviceF);
|
2004-03-23 12:10:32 +00:00
|
|
|
generator.Emit(OpCodes.Newobj, Arguments.GetDBusTypeConstructor(inParType, parType));
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, Arguments_AppendMI, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void EmitOut(ILGenerator generator, Type parType, int parN)
|
|
|
|
|
{
|
|
|
|
|
Type outParType = Arguments.MatchType(parType);
|
|
|
|
|
//generator.EmitWriteLine("enumerator.MoveNext()");
|
|
|
|
|
generator.Emit(OpCodes.Ldloc_2);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, IEnumerator_MoveNextMI, null);
|
|
|
|
|
|
|
|
|
|
//generator.EmitWriteLine("return (" + parType + ") ((DBusType.IDBusType) enumerator.Current).Get(typeof(" + parType + "))");
|
|
|
|
|
generator.Emit(OpCodes.Pop);
|
|
|
|
|
if (parN > 0) {
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_S, parN + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
generator.Emit(OpCodes.Ldloc_2);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, IEnumerator_CurrentMI, null);
|
|
|
|
|
generator.Emit(OpCodes.Castclass, typeof(DBusType.IDBusType));
|
|
|
|
|
generator.Emit(OpCodes.Ldtoken, parType);
|
|
|
|
|
generator.EmitCall(OpCodes.Call, Type_GetTypeFromHandleMI, null);
|
|
|
|
|
generator.EmitCall(OpCodes.Callvirt, IDBusType_GetMI, null);
|
|
|
|
|
|
|
|
|
|
// Call the DBusType EmitMarshalOut to make it emit itself
|
|
|
|
|
object[] pars = new object[] {generator, parType, parN == 0};
|
|
|
|
|
outParType.InvokeMember("EmitMarshalOut", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, pars, null);
|
|
|
|
|
|
|
|
|
|
if (parN == 0) {
|
|
|
|
|
generator.Emit(OpCodes.Stloc_3);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-03-13 01:13:04 +00:00
|
|
|
public void BuildConstructor(ref TypeBuilder typeB, FieldInfo serviceF, FieldInfo pathF, MethodInfo signalCalledMI, FieldInfo deleF)
|
2004-03-23 12:10:32 +00:00
|
|
|
{
|
2004-03-23 18:07:48 +00:00
|
|
|
Type[] pars = {typeof(Service), typeof(string)};
|
2004-03-23 12:10:32 +00:00
|
|
|
ConstructorBuilder constructor = typeB.DefineConstructor(MethodAttributes.RTSpecialName |
|
|
|
|
|
MethodAttributes.Public,
|
|
|
|
|
CallingConventions.Standard, pars);
|
|
|
|
|
|
|
|
|
|
ILGenerator generator = constructor.GetILGenerator();
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Call, this.introspector.Constructor);
|
2004-03-26 15:25:59 +00:00
|
|
|
//generator.EmitWriteLine("service = myService");
|
2004-03-23 12:10:32 +00:00
|
|
|
generator.Emit(OpCodes.Ldarg_1);
|
|
|
|
|
generator.Emit(OpCodes.Stsfld, serviceF);
|
2004-03-26 15:25:59 +00:00
|
|
|
//generator.EmitWriteLine("this.pathName = pathName");
|
2004-03-23 12:10:32 +00:00
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
2004-03-23 18:07:48 +00:00
|
|
|
generator.Emit(OpCodes.Ldarg_2);
|
2004-03-23 12:10:32 +00:00
|
|
|
generator.Emit(OpCodes.Stfld, pathF);
|
2005-03-13 01:13:04 +00:00
|
|
|
|
|
|
|
|
//generator.EmitWriteLine("this.delegate_created = new Service.SignalCalledHandler(Service_SignalCalled)");
|
2004-03-26 15:25:59 +00:00
|
|
|
generator.Emit(OpCodes.Ldarg_1);
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Ldftn, signalCalledMI);
|
|
|
|
|
generator.Emit(OpCodes.Newobj, Service_SignalCalledHandlerC);
|
2005-03-13 01:13:04 +00:00
|
|
|
generator.Emit(OpCodes.Stloc_0);
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Ldloc_0);
|
|
|
|
|
generator.Emit(OpCodes.Stfld, deleF);
|
|
|
|
|
|
|
|
|
|
//generator.EmitWriteLine("myService.SignalCalled += this.delegate_created");
|
|
|
|
|
generator.Emit(OpCodes.Ldloc_0);
|
2004-03-26 15:25:59 +00:00
|
|
|
generator.EmitCall(OpCodes.Callvirt, Service_AddSignalCalledMI, null);
|
2004-03-23 12:10:32 +00:00
|
|
|
|
2004-03-26 15:25:59 +00:00
|
|
|
//generator.EmitWriteLine("return");
|
|
|
|
|
generator.Emit(OpCodes.Ret);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void BuildSignalConstructor(ref TypeBuilder typeB, FieldInfo serviceF, FieldInfo pathF)
|
|
|
|
|
{
|
|
|
|
|
Type[] pars = {typeof(Service), typeof(string)};
|
|
|
|
|
ConstructorBuilder constructor = typeB.DefineConstructor(MethodAttributes.RTSpecialName |
|
|
|
|
|
MethodAttributes.Public,
|
|
|
|
|
CallingConventions.Standard, pars);
|
|
|
|
|
|
|
|
|
|
ILGenerator generator = constructor.GetILGenerator();
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Call, this.introspector.Constructor);
|
|
|
|
|
//generator.EmitWriteLine("service = myService");
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_1);
|
|
|
|
|
generator.Emit(OpCodes.Stsfld, serviceF);
|
|
|
|
|
//generator.EmitWriteLine("this.pathName = pathName");
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_0);
|
|
|
|
|
generator.Emit(OpCodes.Ldarg_2);
|
|
|
|
|
generator.Emit(OpCodes.Stfld, pathF);
|
|
|
|
|
|
|
|
|
|
//generator.EmitWriteLine("return");
|
2004-03-23 12:10:32 +00:00
|
|
|
generator.Emit(OpCodes.Ret);
|
|
|
|
|
}
|
|
|
|
|
|
2005-03-13 01:13:04 +00:00
|
|
|
public void BuildFinalizer (TypeBuilder tb, FieldInfo fi)
|
|
|
|
|
{
|
|
|
|
|
// Note that this is a *HORRIBLE* example of how to build a finalizer
|
|
|
|
|
// It doesn't use the try/finally to chain to Object::Finalize. However,
|
|
|
|
|
// because that is always going to be a nop, lets just ignore that here.
|
|
|
|
|
// If you are trying to find the right code, look at what mcs does ;-).
|
|
|
|
|
|
|
|
|
|
MethodBuilder mb = tb.DefineMethod("Finalize",
|
|
|
|
|
MethodAttributes.Family |
|
|
|
|
|
MethodAttributes.HideBySig |
|
|
|
|
|
MethodAttributes.Virtual,
|
|
|
|
|
typeof (void),
|
|
|
|
|
new Type [0]);
|
|
|
|
|
ILGenerator generator = mb.GetILGenerator();
|
|
|
|
|
|
|
|
|
|
//generator.EmitWriteLine("this.service.SignalCalled -= this.delegate_created");
|
2005-03-13 02:05:56 +00:00
|
|
|
generator.Emit (OpCodes.Ldarg_0);
|
2005-03-13 01:13:04 +00:00
|
|
|
generator.Emit (OpCodes.Ldfld, fi);
|
|
|
|
|
generator.Emit (OpCodes.Call, Service_RemoveSignalCalledMI);
|
|
|
|
|
generator.Emit (OpCodes.Ret);
|
|
|
|
|
}
|
|
|
|
|
|
2004-03-26 15:25:59 +00:00
|
|
|
public object GetSignalProxy()
|
|
|
|
|
{
|
|
|
|
|
Type proxyType = Service.ProxyAssembly.GetType(ObjectName + ".SignalProxy");
|
|
|
|
|
|
|
|
|
|
if (proxyType == null) {
|
|
|
|
|
// Build the type
|
|
|
|
|
TypeBuilder typeB = Service.Module.DefineType(ObjectName + ".SignalProxy",
|
|
|
|
|
TypeAttributes.Public,
|
|
|
|
|
this.type);
|
|
|
|
|
|
|
|
|
|
FieldBuilder serviceF = typeB.DefineField("service",
|
|
|
|
|
typeof(Service),
|
|
|
|
|
FieldAttributes.Private |
|
|
|
|
|
FieldAttributes.Static);
|
|
|
|
|
FieldBuilder pathF = typeB.DefineField("pathName",
|
|
|
|
|
typeof(string),
|
|
|
|
|
FieldAttributes.Private);
|
|
|
|
|
|
|
|
|
|
BuildSignalConstructor(ref typeB, serviceF, pathF);
|
|
|
|
|
|
|
|
|
|
// Build the signal handlers
|
|
|
|
|
foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {
|
|
|
|
|
InterfaceProxy interfaceProxy = (InterfaceProxy) interfaceEntry.Value;
|
|
|
|
|
foreach (DictionaryEntry signalEntry in interfaceProxy.Signals) {
|
|
|
|
|
EventInfo eventE = (EventInfo) signalEntry.Value;
|
|
|
|
|
BuildSignalHandler(eventE, interfaceProxy, ref typeB, serviceF, pathF);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proxyType = typeB.CreateType();
|
2004-03-23 12:10:32 +00:00
|
|
|
|
2004-03-26 15:25:59 +00:00
|
|
|
// Uncomment the following line to produce a DLL of the
|
|
|
|
|
// constructed assembly which can then be examined using
|
|
|
|
|
// monodis. Note that in order for this to work you should copy
|
|
|
|
|
// the client assembly as a dll file so that monodis can pick it
|
|
|
|
|
// up.
|
|
|
|
|
//Service.ProxyAssembly.Save("proxy.dll");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Type [] parTypes = new Type[] {typeof(Service), typeof(string)};
|
|
|
|
|
object [] pars = new object[] {Service, pathName};
|
|
|
|
|
|
|
|
|
|
ConstructorInfo constructor = proxyType.GetConstructor(parTypes);
|
|
|
|
|
object instance = constructor.Invoke(pars);
|
|
|
|
|
return instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public object GetProxy()
|
|
|
|
|
{
|
|
|
|
|
Type proxyType = Service.ProxyAssembly.GetType(ObjectName + ".Proxy");
|
2004-03-23 12:10:32 +00:00
|
|
|
|
2004-03-24 14:42:41 +00:00
|
|
|
if (proxyType == null) {
|
|
|
|
|
// Build the type
|
2004-03-26 15:25:59 +00:00
|
|
|
TypeBuilder typeB = Service.Module.DefineType(ObjectName + ".Proxy", TypeAttributes.Public, this.type);
|
2004-03-24 14:42:41 +00:00
|
|
|
|
|
|
|
|
FieldBuilder serviceF = typeB.DefineField("service",
|
|
|
|
|
typeof(Service),
|
|
|
|
|
FieldAttributes.Private |
|
|
|
|
|
FieldAttributes.Static);
|
|
|
|
|
FieldBuilder pathF = typeB.DefineField("pathName",
|
|
|
|
|
typeof(string),
|
|
|
|
|
FieldAttributes.Private);
|
2005-03-13 01:13:04 +00:00
|
|
|
FieldBuilder deleF = typeB.DefineField("delegate_created",
|
|
|
|
|
typeof(Service.SignalCalledHandler),
|
|
|
|
|
FieldAttributes.Private);
|
|
|
|
|
BuildFinalizer (typeB, deleF);
|
2004-03-24 14:42:41 +00:00
|
|
|
|
2004-03-26 15:25:59 +00:00
|
|
|
MethodInfo signalCalledMI = BuildSignalCalled(ref typeB, serviceF, pathF);
|
2005-03-13 01:13:04 +00:00
|
|
|
BuildConstructor(ref typeB, serviceF, pathF, signalCalledMI, deleF);
|
2004-03-24 14:42:41 +00:00
|
|
|
|
|
|
|
|
// Build the methods
|
|
|
|
|
foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {
|
|
|
|
|
InterfaceProxy interfaceProxy = (InterfaceProxy) interfaceEntry.Value;
|
|
|
|
|
foreach (DictionaryEntry methodEntry in interfaceProxy.Methods) {
|
|
|
|
|
MethodInfo method = (MethodInfo) methodEntry.Value;
|
|
|
|
|
BuildMethod(method, interfaceProxy, ref typeB, serviceF, pathF);
|
|
|
|
|
}
|
2004-03-23 18:07:48 +00:00
|
|
|
}
|
2004-03-24 14:42:41 +00:00
|
|
|
|
|
|
|
|
proxyType = typeB.CreateType();
|
2004-03-23 12:10:32 +00:00
|
|
|
|
2004-03-24 14:42:41 +00:00
|
|
|
// Uncomment the following line to produce a DLL of the
|
|
|
|
|
// constructed assembly which can then be examined using
|
|
|
|
|
// monodis. Note that in order for this to work you should copy
|
|
|
|
|
// the client assembly as a dll file so that monodis can pick it
|
|
|
|
|
// up.
|
2004-03-26 15:25:59 +00:00
|
|
|
//Service.ProxyAssembly.Save("proxy.dll");
|
2004-03-24 14:42:41 +00:00
|
|
|
}
|
|
|
|
|
|
2004-03-23 18:07:48 +00:00
|
|
|
Type [] parTypes = new Type[] {typeof(Service), typeof(string)};
|
|
|
|
|
object [] pars = new object[] {Service, pathName};
|
2004-03-23 12:10:32 +00:00
|
|
|
|
|
|
|
|
ConstructorInfo constructor = proxyType.GetConstructor(parTypes);
|
|
|
|
|
object instance = constructor.Invoke(pars);
|
|
|
|
|
return instance;
|
|
|
|
|
}
|
2004-03-26 15:25:59 +00:00
|
|
|
|
|
|
|
|
private Service Service
|
2004-03-23 12:10:32 +00:00
|
|
|
{
|
2004-03-23 18:07:48 +00:00
|
|
|
get {
|
|
|
|
|
return this.service;
|
|
|
|
|
}
|
2004-03-23 12:10:32 +00:00
|
|
|
}
|
|
|
|
|
|
2004-03-26 15:25:59 +00:00
|
|
|
private string ObjectName
|
2004-03-23 12:10:32 +00:00
|
|
|
{
|
2004-03-23 18:07:48 +00:00
|
|
|
get {
|
2004-03-26 15:25:59 +00:00
|
|
|
return this.introspector.ToString();
|
2004-03-23 18:07:48 +00:00
|
|
|
}
|
2004-03-23 12:10:32 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|