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

Commit

Permalink
properties: Implement GetAll response
Browse files Browse the repository at this point in the history
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'.
  • Loading branch information
arfbtwn committed Feb 22, 2015
1 parent 2a4f701 commit 50ea457
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 3 deletions.
32 changes: 29 additions & 3 deletions src/ExportObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ internal class MethodCall {
}

internal class MethodDictionary : Dictionary<string, MethodCall> { }
internal class PropertyDictionary : Dictionary<string, PropertyCall> { }
internal class PropertyDictionary : Dictionary<string, PropertyCall> {
public MethodCaller All { get; set; }
}

internal class InterfaceMethods : Dictionary<string, MethodDictionary> { }
internal class InterfaceProperties : Dictionary<string, PropertyDictionary> { }
Expand Down Expand Up @@ -59,6 +61,21 @@ public MethodCall GetMethodCall (string iface, string name)
);
}

public MethodCaller GetPropertyAllCall (string iface)
{
PropertyDictionary calls;
if (!Properties.TryGetValue(iface, out calls)) {
Properties [iface] = calls = new PropertyDictionary ();
}

if (null == calls.All) {
Type it = Mapper.GetInterfaceType (ObjectType, iface);
calls.All = TypeImplementer.GenGetAllCall (it);
}

return calls.All;
}

public PropertyCall GetPropertyCall (string iface, string name)
{
return Lookup<InterfaceProperties, PropertyDictionary, string, string, PropertyCall> (
Expand Down Expand Up @@ -238,8 +255,17 @@ private void HandlePropertyCall (MessageContainer method_call)
string face = (string) args [0];

if ("GetAll" == method_call.Member) {
// TODO
throw new NotImplementedException ();
Signature asv = Signature.MakeDict (Signature.StringSig, Signature.VariantSig);

MethodCaller call = typeMembers [Object.GetType ()].GetPropertyAllCall (face);

Exception ex = null;
try {
call (Object, msgReader, msg, retWriter);
} catch (Exception e) { ex = e; }

IssueReply (method_call, asv, retWriter, null, ex);
return;
}

string name = (string) args [1];
Expand Down
49 changes: 49 additions & 0 deletions src/TypeImplementer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,55 @@ internal static MethodCaller GenSetCall (PropertyInfo target)
return (MethodCaller) method.CreateDelegate (typeof(MethodCaller));
}

internal static MethodCaller GenGetAllCall (Type @interface)
{
var parms = new Type[] {
typeof (object),
typeof (MessageReader),
typeof (Message),
typeof (MessageWriter)
};
var method = new DynamicMethod ("PropertyGetAll", typeof(void), parms, typeof(MessageReader));

var ilg = method.GetILGenerator ();
var dctT = typeof(Dictionary<string, object>);

var strObj = new [] { typeof(string), typeof(object) };
var dctConstructor = dctT.GetConstructor (new Type[0]);
var dctAdd = dctT.GetMethod ("Add", strObj);

var accessors = @interface.GetProperties ().Where (x => null != x.GetGetMethod());

var dct = ilg.DeclareLocal (dctT);
var val = ilg.DeclareLocal (typeof(object));

ilg.Emit (OpCodes.Newobj, dctConstructor);
ilg.Emit (OpCodes.Stloc, dct);
foreach (var property in accessors) {
var mi = property.GetGetMethod ();

ilg.Emit (OpCodes.Ldarg_0);
ilg.Emit (mi.IsFinal ? OpCodes.Call : OpCodes.Callvirt, mi);
if (mi.ReturnType.IsValueType) {
ilg.Emit (OpCodes.Box, mi.ReturnType);
}
// TODO: Cast object references to typeof(object)?
ilg.Emit (OpCodes.Stloc, val);

ilg.Emit (OpCodes.Ldloc, dct);
ilg.Emit (OpCodes.Ldstr, property.Name);
ilg.Emit (OpCodes.Ldloc, val);
ilg.Emit (OpCodes.Call, dctAdd);
}
ilg.Emit (OpCodes.Ldarg_3);
ilg.Emit (OpCodes.Ldloc, dct);
GenWriter (ilg, dctT);

ilg.Emit (OpCodes.Ret);

return (MethodCaller) method.CreateDelegate (typeof(MethodCaller));
}

internal static MethodCaller GenCaller (MethodInfo target)
{
DynamicMethod hookupMethod = GenReadMethod (target);
Expand Down
36 changes: 36 additions & 0 deletions tests/ExportInterfaceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;

using NUnit.Framework;
Expand Down Expand Up @@ -161,6 +162,41 @@ public void Property ()
Assert.AreEqual (i + 1, test.SomeProp);
}

[Test]
public void AllProperties ()
{
var args = string.Format (
"--dest={0} --type=method_call --print-reply " +
"{1} org.freedesktop.DBus.Properties.GetAll string:{0}",
bus_name,
path
);
Process dbus = new Process {
StartInfo = new ProcessStartInfo {
FileName = "dbus-send",
Arguments = args,
RedirectStandardOutput = true,
UseShellExecute = false
}
};

var iterator = new Thread(() => { do { Bus.Session.Iterate(); } while (true); });
iterator.Start ();

if (dbus.Start ()) {
dbus.WaitForExit ();

string output = dbus.StandardOutput.ReadToEnd ();
Assert.IsNotEmpty (output);
// FIXME: Use a regular expression?
Assert.IsTrue (output.Contains ("SomeProp"));
} else {
Assert.Ignore ("Failed to start test program");
}

iterator.Abort ();
}

/// <summary>
///
/// </summary>
Expand Down

0 comments on commit 50ea457

Please sign in to comment.