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 Array : IDBusType 00014 { 00015 public const char Code = 'a'; 00016 private System.Array val; 00017 private ArrayList elements; 00018 private Type elementType; 00019 private Service service = null; 00020 00021 private Array() 00022 { 00023 } 00024 00025 public Array(System.Array val, Service service) 00026 { 00027 this.val = val; 00028 this.elementType = Arguments.MatchType(val.GetType().GetElementType()); 00029 this.service = service; 00030 } 00031 00032 public Array(IntPtr iter, Service service) 00033 { 00034 this.service = service; 00035 00036 IntPtr arrayIter = Marshal.AllocCoTaskMem(Arguments.DBusMessageIterSize); 00037 00038 int elementTypeCode = dbus_message_iter_get_element_type (iter); 00039 dbus_message_iter_recurse (iter, arrayIter); 00040 this.elementType = (Type) Arguments.DBusTypes [(char) elementTypeCode]; 00041 00042 elements = new ArrayList (); 00043 00044 if (dbus_message_iter_get_arg_type (arrayIter) != 0) { 00045 do { 00046 object [] pars = new Object[2]; 00047 pars[0] = arrayIter; 00048 pars[1] = service; 00049 DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars); 00050 elements.Add(dbusType); 00051 } while (dbus_message_iter_next(arrayIter)); 00052 } 00053 00054 Marshal.FreeCoTaskMem(arrayIter); 00055 } 00056 00057 public void Append(IntPtr iter) 00058 { 00059 IntPtr arrayIter = Marshal.AllocCoTaskMem (Arguments.DBusMessageIterSize); 00060 00061 if (!dbus_message_iter_open_container (iter, 00062 (int) Code, 00063 Arguments.GetCodeAsString (elementType), 00064 arrayIter)) { 00065 throw new ApplicationException("Failed to append array argument: " + val); 00066 } 00067 00068 foreach (object element in this.val) { 00069 object [] pars = new Object[2]; 00070 pars[0] = element; 00071 pars[1] = this.service; 00072 DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars); 00073 dbusType.Append(arrayIter); 00074 } 00075 00076 if (!dbus_message_iter_close_container (iter, arrayIter)) { 00077 throw new ApplicationException ("Failed to append array argument: " + val); 00078 } 00079 00080 Marshal.FreeCoTaskMem (arrayIter); 00081 } 00082 00083 public static bool Suits(System.Type type) 00084 { 00085 if (type.IsArray) { 00086 return true; 00087 } 00088 00089 return false; 00090 } 00091 00092 public static void EmitMarshalIn(ILGenerator generator, Type type) 00093 { 00094 if (type.IsByRef) { 00095 generator.Emit(OpCodes.Ldind_Ref); 00096 } 00097 } 00098 00099 public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn) 00100 { 00101 generator.Emit(OpCodes.Castclass, type); 00102 if (!isReturn) { 00103 generator.Emit(OpCodes.Stind_Ref); 00104 } 00105 } 00106 00107 public object Get() 00108 { 00109 throw new ArgumentException("Cannot call Get on an Array without specifying type."); 00110 } 00111 00112 public object Get(System.Type type) 00113 { 00114 if (type.IsArray) 00115 type = type.GetElementType (); 00116 00117 if (Arguments.Suits(elementType, type.UnderlyingSystemType)) { 00118 this.val = System.Array.CreateInstance(type.UnderlyingSystemType, elements.Count); 00119 int i = 0; 00120 foreach (DBusType.IDBusType element in elements) { 00121 this.val.SetValue(element.Get(type.UnderlyingSystemType), i++); 00122 } 00123 } else { 00124 throw new ArgumentException("Cannot cast DBus.Type.Array to type '" + type.ToString() + "'"); 00125 } 00126 00127 return this.val; 00128 } 00129 00130 [DllImport("dbus-1")] 00131 private extern static bool dbus_message_iter_open_container (IntPtr iter, 00132 int containerType, 00133 string elementType, 00134 IntPtr subIter); 00135 00136 [DllImport("dbus-1")] 00137 private extern static bool dbus_message_iter_close_container (IntPtr iter, 00138 IntPtr subIter); 00139 00140 [DllImport("dbus-1")] 00141 private extern static int dbus_message_iter_get_element_type(IntPtr iter); 00142 00143 [DllImport("dbus-1")] 00144 private extern static int dbus_message_iter_get_arg_type(IntPtr iter); 00145 00146 [DllImport("dbus-1")] 00147 private extern static void dbus_message_iter_recurse(IntPtr iter, IntPtr subIter); 00148 00149 [DllImport("dbus-1")] 00150 private extern static bool dbus_message_iter_next(IntPtr iter); 00151 00152 [DllImport("dbus-1")] 00153 private extern static bool dbus_message_iter_has_next (IntPtr iter); 00154 } 00155 }