00001 using System;
00002 using System.Collections;
00003 using System.Runtime.InteropServices;
00004 using System.Reflection.Emit;
00005
00006 using DBus;
00007
00008 namespace DBus.DBusType
00009 {
00013 public class Dict : IDBusType
00014 {
00015 public const char Code = 'm';
00016 private Hashtable val;
00017
00018 private Dict()
00019 {
00020 }
00021
00022 public Dict(IDictionary val, Service service)
00023 {
00024 this.val = new Hashtable();
00025 foreach (DictionaryEntry entry in val) {
00026 this.val.Add(entry.Key, entry.Value);
00027 }
00028 }
00029
00030 public Dict(IntPtr iter, Service service)
00031 {
00032 IntPtr dictIter = Marshal.AllocCoTaskMem(Arguments.DBusMessageIterSize);
00033
00034 bool notEmpty = dbus_message_iter_init_dict_iterator(iter, dictIter);
00035
00036 this.val = new Hashtable();
00037
00038 if (notEmpty) {
00039 do {
00040 string key = dbus_message_iter_get_dict_key(dictIter);
00041
00042
00043 Type elementType = (Type) DBus.Arguments.DBusTypes[(char) dbus_message_iter_get_arg_type(dictIter)];
00044 object [] pars = new Object[2];
00045 pars[0] = dictIter;
00046 pars[1] = service;
00047 DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars);
00048 this.val.Add(key, dbusType);
00049 } while (dbus_message_iter_next(dictIter));
00050 }
00051
00052 Marshal.FreeCoTaskMem(dictIter);
00053 }
00054
00055 public void Append(IntPtr iter)
00056 {
00057 IntPtr dictIter = Marshal.AllocCoTaskMem(Arguments.DBusMessageIterSize);
00058
00059 if (!dbus_message_iter_append_dict(iter,
00060 dictIter)) {
00061 throw new ApplicationException("Failed to append DICT argument:" + val);
00062 }
00063
00064 foreach (DictionaryEntry entry in this.val) {
00065 if (!dbus_message_iter_append_dict_key(dictIter, (string) entry.Key)) {
00066 throw new ApplicationException("Failed to append DICT key:" + entry.Key);
00067 }
00068
00069
00070 Type elementType = Arguments.MatchType(entry.Value.GetType());
00071 object [] pars = new Object[1];
00072 pars[0] = entry.Value;
00073 DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars);
00074 dbusType.Append(dictIter);
00075 }
00076
00077 Marshal.FreeCoTaskMem(dictIter);
00078 }
00079
00080 public static bool Suits(System.Type type)
00081 {
00082 if (typeof(IDictionary).IsAssignableFrom(type)) {
00083 return true;
00084 }
00085
00086 return false;
00087 }
00088
00089 public static void EmitMarshalIn(ILGenerator generator, Type type)
00090 {
00091 if (type.IsByRef) {
00092 generator.Emit(OpCodes.Ldind_Ref);
00093 }
00094 }
00095
00096 public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn)
00097 {
00098 generator.Emit(OpCodes.Castclass, type);
00099 if (!isReturn) {
00100 generator.Emit(OpCodes.Stind_Ref);
00101 }
00102 }
00103
00104 public object Get()
00105 {
00106 return Get(typeof(Hashtable));
00107 }
00108
00109 public object Get(System.Type type)
00110 {
00111 IDictionary retVal;
00112
00113 if (Suits(type)) {
00114 retVal = (IDictionary) Activator.CreateInstance(type, new object[0]);
00115 foreach (DictionaryEntry entry in this.val) {
00116 retVal.Add(entry.Key, ((IDBusType) entry.Value).Get());
00117 }
00118 } else {
00119 throw new ArgumentException("Cannot cast DBus.Type.Dict to type '" + type.ToString() + "'");
00120 }
00121
00122 return retVal;
00123 }
00124
00125 [DllImport("dbus-1")]
00126 private extern static bool dbus_message_iter_init_dict_iterator(IntPtr iter,
00127 IntPtr dictIter);
00128
00129 [DllImport("dbus-1")]
00130 private extern static bool dbus_message_iter_append_dict(IntPtr iter,
00131 IntPtr dictIter);
00132
00133 [DllImport("dbus-1")]
00134 private extern static bool dbus_message_iter_has_next(IntPtr iter);
00135
00136 [DllImport("dbus-1")]
00137 private extern static bool dbus_message_iter_next(IntPtr iter);
00138
00139 [DllImport("dbus-1")]
00140 private extern static string dbus_message_iter_get_dict_key (IntPtr dictIter);
00141
00142 [DllImport("dbus-1")]
00143 private extern static bool dbus_message_iter_append_dict_key (IntPtr dictIter,
00144 string value);
00145 [DllImport("dbus-1")]
00146 private extern static int dbus_message_iter_get_arg_type(IntPtr iter);
00147 }
00148 }