Array.cs

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 string GetElementCodeAsString ()
00058     {
00059       string ret = System.String.Empty;
00060       Type t = val.GetType ().GetElementType ();
00061 
00062       while (true) {
00063         ret += Arguments.GetCodeAsString (Arguments.MatchType(t));
00064 
00065         if (t.IsArray)
00066           t = t.GetElementType ();
00067         else
00068           break;
00069       }
00070      
00071       return ret; 
00072     }
00073     
00074     public void Append(IntPtr iter)
00075     {
00076       IntPtr arrayIter = Marshal.AllocCoTaskMem (Arguments.DBusMessageIterSize);
00077 
00078       if (!dbus_message_iter_open_container (iter,
00079                                              (int) Code, GetElementCodeAsString(),
00080                                              arrayIter)) {
00081         throw new ApplicationException("Failed to append array argument: " + val);
00082       }
00083       
00084       foreach (object element in this.val) {
00085         object [] pars = new Object[2];
00086         pars[0] = element;
00087         pars[1] = this.service;
00088         DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars);
00089         dbusType.Append(arrayIter);
00090       }
00091 
00092       if (!dbus_message_iter_close_container (iter, arrayIter)) {
00093         throw new ApplicationException ("Failed to append array argument: " + val);
00094       }
00095 
00096       Marshal.FreeCoTaskMem (arrayIter);
00097     }    
00098 
00099     public static bool Suits(System.Type type) 
00100     {
00101       Type type2 = type.GetElementType ();
00102       if (type.IsArray || (type2 != null && type2.IsArray)) {
00103         return true;
00104       }
00105       
00106       return false;
00107     }
00108 
00109     public static void EmitMarshalIn(ILGenerator generator, Type type)
00110     {
00111       if (type.IsByRef) {
00112         generator.Emit(OpCodes.Ldind_Ref);
00113       }
00114     }
00115 
00116     public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn) 
00117     {
00118       generator.Emit(OpCodes.Castclass, type);
00119       if (!isReturn) {
00120         generator.Emit(OpCodes.Stind_Ref);
00121       }
00122     }
00123     
00124     public object Get() 
00125     {
00126       throw new ArgumentException("Cannot call Get on an Array without specifying type.");
00127     }
00128 
00129     public object Get(System.Type type)
00130     {
00131       if (type.IsArray)
00132         type = type.GetElementType ();
00133 
00134       if (Arguments.Suits(elementType, type.UnderlyingSystemType)) {
00135         this.val = System.Array.CreateInstance(type.UnderlyingSystemType, elements.Count);
00136         int i = 0;
00137         foreach (DBusType.IDBusType element in elements) {
00138           this.val.SetValue(element.Get(type.UnderlyingSystemType), i++);
00139         }       
00140       } else {
00141         throw new ArgumentException("Cannot cast DBus.Type.Array to type '" + type.ToString() + "'");
00142       }
00143         
00144         return this.val;
00145     }    
00146 
00147     [DllImport("dbus-1")]
00148     private extern static bool dbus_message_iter_open_container (IntPtr iter,
00149                                                                  int containerType,
00150                                                                  string elementType,
00151                                                                  IntPtr subIter);
00152 
00153     [DllImport("dbus-1")]
00154     private extern static bool dbus_message_iter_close_container (IntPtr iter,
00155                                                                   IntPtr subIter);
00156  
00157     [DllImport("dbus-1")]
00158     private extern static int dbus_message_iter_get_element_type(IntPtr iter);
00159 
00160     [DllImport("dbus-1")]
00161     private extern static int dbus_message_iter_get_arg_type(IntPtr iter);
00162 
00163     [DllImport("dbus-1")]
00164     private extern static void dbus_message_iter_recurse(IntPtr iter, IntPtr subIter);
00165 
00166     [DllImport("dbus-1")]
00167     private extern static bool dbus_message_iter_next(IntPtr iter);
00168 
00169     [DllImport("dbus-1")]
00170     private extern static bool dbus_message_iter_has_next (IntPtr iter);
00171   }
00172 }

Generated on Wed Feb 27 10:13:37 2008 for D-BUS by  doxygen 1.4.6