2
using System.Collections;
3
using System.Reflection;
4
using System.Runtime.InteropServices;
8
// Holds the arguments of a message. Provides methods for appending
9
// arguments and to assist in matching .NET types with D-BUS types.
10
public class Arguments : IEnumerable, IDisposable
12
// Must follow sizeof(DBusMessageIter)
13
internal const int DBusMessageIterSize = 14*4;
14
private static Hashtable dbusTypes = null;
15
private Message message;
16
private IntPtr appenderIter;
17
private IEnumerator enumerator = null;
19
internal Arguments (Message message)
21
this.appenderIter = Marshal.AllocCoTaskMem(DBusMessageIterSize);
22
this.message = message;
25
private void Dispose (bool disposing)
27
Marshal.FreeCoTaskMem(appenderIter);
30
public void Dispose ()
33
GC.SuppressFinalize (this);
41
// Checks the suitability of a D-BUS type for supporting a .NET
43
public static bool Suits(Type dbusType, Type type)
45
object [] pars = new object[1];
48
return (bool) dbusType.InvokeMember("Suits", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, pars, null);
51
// Find a suitable match for the given .NET type or throw an
52
// exception if one can't be found.
53
public static Type MatchType(Type type)
55
foreach(Type dbusType in DBusTypes.Values) {
56
if (Suits(dbusType, type)) {
61
throw new ApplicationException("No suitable DBUS type found for type '" + type + "'");
65
public static Hashtable DBusTypes {
68
if (dbusTypes == null) {
69
dbusTypes = new Hashtable();
71
foreach (Type type in Assembly.GetAssembly(typeof(DBusType.IDBusType)).GetTypes()) {
72
if (type != typeof(DBusType.IDBusType) && typeof(DBusType.IDBusType).IsAssignableFrom(type)) {
73
dbusTypes.Add(GetCode(type), type);
83
public void Append(DBusType.IDBusType dbusType)
85
dbusType.Append(appenderIter);
88
// Append an argument of the specified type
89
private void AppendType(Type type, object val)
91
object [] pars = new Object[2];
93
pars[1] = message.Service;
94
DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(MatchType(type), pars);
98
// Append the results of a method call
99
public void AppendResults(MethodInfo method, object retVal, object [] parameters)
103
if (method.ReturnType != typeof(void)) {
104
AppendType(method.ReturnType, retVal);
107
for (int i = 0; i < method.GetParameters().Length; i++) {
108
ParameterInfo par = method.GetParameters()[i];
109
if (par.IsOut || par.ParameterType.ToString().EndsWith("&")) {
110
// It's an OUT or INOUT parameter.
111
AppendType(par.ParameterType.UnderlyingSystemType, parameters[i]);
116
// Get the parameters
117
public object[] GetParameters(MethodInfo method)
119
ParameterInfo[] pars = method.GetParameters();
120
ArrayList paramList = new ArrayList();
122
enumerator = GetEnumerator();
123
foreach (ParameterInfo par in pars) {
125
// It's an IN or INOUT paramter.
126
enumerator.MoveNext();
127
DBusType.IDBusType dbusType = (DBusType.IDBusType) enumerator.Current;
128
paramList.Add(dbusType.Get(par.ParameterType));
130
// It's an OUT so just create a parameter for it
136
return paramList.ToArray();
139
// Parse the IN & REF parameters to a method and return the types in a list.
140
public static object[] ParseInParameters(MethodInfo method)
142
ArrayList types = new ArrayList();
144
ParameterInfo[] pars = method.GetParameters();
145
foreach (ParameterInfo par in pars) {
147
types.Add(MatchType(par.ParameterType));
151
return types.ToArray();
154
// Parse the OUT & REF parameters to a method and return the types in a list.
155
public static object[] ParseOutParameters(MethodInfo method)
157
ArrayList types = new ArrayList();
159
ParameterInfo[] pars = method.GetParameters();
160
foreach (ParameterInfo par in pars) {
161
if (par.IsOut || par.ParameterType.ToString().EndsWith("&")) {
162
types.Add(MatchType(par.ParameterType));
166
return types.ToArray();
169
// Get the appropriate constructor for a D-BUS type
170
public static ConstructorInfo GetDBusTypeConstructor(Type dbusType, Type type)
172
Type constructorType;
175
constructorType = typeof (System.Array);
176
else if (type.IsEnum)
177
constructorType = Enum.GetUnderlyingType (type);
179
constructorType = type.UnderlyingSystemType;
181
ConstructorInfo constructor = dbusType.GetConstructor(new Type[] {constructorType, typeof(Service)});
182
if (constructor == null)
183
throw new ArgumentException("There is no valid constructor for '" + dbusType + "' from type '" + type + "'");
188
// Get the type code for a given D-BUS type
189
public static char GetCode(Type dbusType)
191
return (char) dbusType.InvokeMember("Code", BindingFlags.Static | BindingFlags.GetField, null, null, null);
194
// Get the type code for a given D-BUS type as a string
195
public static string GetCodeAsString (Type dbusType)
197
return GetCode (dbusType).ToString ();
200
// Get a complete method signature
201
public override string ToString()
203
IntPtr iter = Marshal.AllocCoTaskMem(DBusMessageIterSize);
206
// Iterate through the parameters getting the type codes to a string
207
bool notEmpty = dbus_message_iter_init(message.RawMessage, iter);
211
char code = (char) dbus_message_iter_get_arg_type(iter);
216
} while (dbus_message_iter_next(iter));
219
Marshal.FreeCoTaskMem(iter);
224
// Move to the next parameter
225
public DBusType.IDBusType GetNext()
227
enumerator.MoveNext();
228
return (DBusType.IDBusType) enumerator.Current;
232
public void InitAppending()
234
dbus_message_iter_init_append(message.RawMessage, appenderIter);
237
// Get the enumerator
238
public IEnumerator GetEnumerator()
240
return new ArgumentsEnumerator(this);
243
private class ArgumentsEnumerator : IEnumerator
245
private Arguments arguments;
246
private bool started = false;
247
private bool notEmpty = false;
248
private IntPtr iter = Marshal.AllocCoTaskMem(Arguments.DBusMessageIterSize);
250
public ArgumentsEnumerator(Arguments arguments)
252
this.arguments = arguments;
256
~ArgumentsEnumerator()
258
Marshal.FreeCoTaskMem(iter);
261
public bool MoveNext()
264
return dbus_message_iter_next(iter);
273
notEmpty = dbus_message_iter_init(arguments.message.RawMessage, iter);
277
public object Current
281
object [] pars = new Object[2];
283
pars[1] = arguments.message.Service;
285
Type type = (Type) DBusTypes[(char) dbus_message_iter_get_arg_type(iter)];
286
DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(type, pars);
293
[DllImport("dbus-1")]
294
private extern static void dbus_message_iter_init_append(IntPtr rawMessage, IntPtr iter);
296
[DllImport("dbus-1")]
297
private extern static bool dbus_message_iter_has_next(IntPtr iter);
299
[DllImport("dbus-1")]
300
private extern static bool dbus_message_iter_next(IntPtr iter);
302
[DllImport("dbus-1")]
303
private extern static bool dbus_message_iter_init(IntPtr rawMessage, IntPtr iter);
305
[DllImport("dbus-1")]
306
private extern static int dbus_message_iter_get_arg_type(IntPtr iter);