Skip to content
This repository was archived by the owner on Nov 8, 2022. It is now read-only.

Commit 50ea457

Browse files
committed
properties: Implement GetAll response
This commit adds a prototype GetAll response and accompanying unit test to demonstrate. Unfortunately the unit test may not work on Windows systems since it calls out to the system utility 'dbus-send'.
1 parent 2a4f701 commit 50ea457

File tree

3 files changed

+114
-3
lines changed

3 files changed

+114
-3
lines changed

src/ExportObject.cs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ internal class MethodCall {
2828
}
2929

3030
internal class MethodDictionary : Dictionary<string, MethodCall> { }
31-
internal class PropertyDictionary : Dictionary<string, PropertyCall> { }
31+
internal class PropertyDictionary : Dictionary<string, PropertyCall> {
32+
public MethodCaller All { get; set; }
33+
}
3234

3335
internal class InterfaceMethods : Dictionary<string, MethodDictionary> { }
3436
internal class InterfaceProperties : Dictionary<string, PropertyDictionary> { }
@@ -59,6 +61,21 @@ public MethodCall GetMethodCall (string iface, string name)
5961
);
6062
}
6163

64+
public MethodCaller GetPropertyAllCall (string iface)
65+
{
66+
PropertyDictionary calls;
67+
if (!Properties.TryGetValue(iface, out calls)) {
68+
Properties [iface] = calls = new PropertyDictionary ();
69+
}
70+
71+
if (null == calls.All) {
72+
Type it = Mapper.GetInterfaceType (ObjectType, iface);
73+
calls.All = TypeImplementer.GenGetAllCall (it);
74+
}
75+
76+
return calls.All;
77+
}
78+
6279
public PropertyCall GetPropertyCall (string iface, string name)
6380
{
6481
return Lookup<InterfaceProperties, PropertyDictionary, string, string, PropertyCall> (
@@ -238,8 +255,17 @@ private void HandlePropertyCall (MessageContainer method_call)
238255
string face = (string) args [0];
239256

240257
if ("GetAll" == method_call.Member) {
241-
// TODO
242-
throw new NotImplementedException ();
258+
Signature asv = Signature.MakeDict (Signature.StringSig, Signature.VariantSig);
259+
260+
MethodCaller call = typeMembers [Object.GetType ()].GetPropertyAllCall (face);
261+
262+
Exception ex = null;
263+
try {
264+
call (Object, msgReader, msg, retWriter);
265+
} catch (Exception e) { ex = e; }
266+
267+
IssueReply (method_call, asv, retWriter, null, ex);
268+
return;
243269
}
244270

245271
string name = (string) args [1];

src/TypeImplementer.cs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,55 @@ internal static MethodCaller GenSetCall (PropertyInfo target)
622622
return (MethodCaller) method.CreateDelegate (typeof(MethodCaller));
623623
}
624624

625+
internal static MethodCaller GenGetAllCall (Type @interface)
626+
{
627+
var parms = new Type[] {
628+
typeof (object),
629+
typeof (MessageReader),
630+
typeof (Message),
631+
typeof (MessageWriter)
632+
};
633+
var method = new DynamicMethod ("PropertyGetAll", typeof(void), parms, typeof(MessageReader));
634+
635+
var ilg = method.GetILGenerator ();
636+
var dctT = typeof(Dictionary<string, object>);
637+
638+
var strObj = new [] { typeof(string), typeof(object) };
639+
var dctConstructor = dctT.GetConstructor (new Type[0]);
640+
var dctAdd = dctT.GetMethod ("Add", strObj);
641+
642+
var accessors = @interface.GetProperties ().Where (x => null != x.GetGetMethod());
643+
644+
var dct = ilg.DeclareLocal (dctT);
645+
var val = ilg.DeclareLocal (typeof(object));
646+
647+
ilg.Emit (OpCodes.Newobj, dctConstructor);
648+
ilg.Emit (OpCodes.Stloc, dct);
649+
foreach (var property in accessors) {
650+
var mi = property.GetGetMethod ();
651+
652+
ilg.Emit (OpCodes.Ldarg_0);
653+
ilg.Emit (mi.IsFinal ? OpCodes.Call : OpCodes.Callvirt, mi);
654+
if (mi.ReturnType.IsValueType) {
655+
ilg.Emit (OpCodes.Box, mi.ReturnType);
656+
}
657+
// TODO: Cast object references to typeof(object)?
658+
ilg.Emit (OpCodes.Stloc, val);
659+
660+
ilg.Emit (OpCodes.Ldloc, dct);
661+
ilg.Emit (OpCodes.Ldstr, property.Name);
662+
ilg.Emit (OpCodes.Ldloc, val);
663+
ilg.Emit (OpCodes.Call, dctAdd);
664+
}
665+
ilg.Emit (OpCodes.Ldarg_3);
666+
ilg.Emit (OpCodes.Ldloc, dct);
667+
GenWriter (ilg, dctT);
668+
669+
ilg.Emit (OpCodes.Ret);
670+
671+
return (MethodCaller) method.CreateDelegate (typeof(MethodCaller));
672+
}
673+
625674
internal static MethodCaller GenCaller (MethodInfo target)
626675
{
627676
DynamicMethod hookupMethod = GenReadMethod (target);

tests/ExportInterfaceTest.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
using System;
77
using System.Collections.Generic;
8+
using System.Diagnostics;
89
using System.Threading;
910

1011
using NUnit.Framework;
@@ -161,6 +162,41 @@ public void Property ()
161162
Assert.AreEqual (i + 1, test.SomeProp);
162163
}
163164

165+
[Test]
166+
public void AllProperties ()
167+
{
168+
var args = string.Format (
169+
"--dest={0} --type=method_call --print-reply " +
170+
"{1} org.freedesktop.DBus.Properties.GetAll string:{0}",
171+
bus_name,
172+
path
173+
);
174+
Process dbus = new Process {
175+
StartInfo = new ProcessStartInfo {
176+
FileName = "dbus-send",
177+
Arguments = args,
178+
RedirectStandardOutput = true,
179+
UseShellExecute = false
180+
}
181+
};
182+
183+
var iterator = new Thread(() => { do { Bus.Session.Iterate(); } while (true); });
184+
iterator.Start ();
185+
186+
if (dbus.Start ()) {
187+
dbus.WaitForExit ();
188+
189+
string output = dbus.StandardOutput.ReadToEnd ();
190+
Assert.IsNotEmpty (output);
191+
// FIXME: Use a regular expression?
192+
Assert.IsTrue (output.Contains ("SomeProp"));
193+
} else {
194+
Assert.Ignore ("Failed to start test program");
195+
}
196+
197+
iterator.Abort ();
198+
}
199+
164200
/// <summary>
165201
///
166202
/// </summary>

0 commit comments

Comments
 (0)