c# Generic way to stringify arrays of structs -
i've searched quite time, have not been able find how generically stringify array of structures in c# @ runtime.
let's have
public enum fieldinfotype { fituint32, fitstruct, fituint32array1d, fituint32array2das1d, fitstruct2das1d, } [attributeusage(attributetargets.field)] public class fieldinfo : attribute { private readonly string _description; private readonly fieldinfotype _type; private readonly int _dim1; private readonly int _dim2; public fieldinfo(string d, fieldinfotype t) { _description = d; _type = t; } public fieldinfo(string d, fieldinfotype t, int d1, int d2) { _description = d; _type = t; _dim1 = d1; _dim2 = d2; } public static void stringtostruct<t>(ref t mystruct, caltextreader tr) { foreach (var field in mystruct.gettype().getfields(bindingflags.instance | bindingflags.nonpublic | bindingflags.public)) { foreach (attribute attr in getcustomattributes(field)) { var info = attr fieldinfo; if (info != null) { fieldinfo fieldinfo = info; var fieldval = field.getvalue(mystruct); switch (fieldinfo._type) { case fieldinfotype.fitstruct: var structure = field.getvalue(mystruct); stringtostruct(ref structure, tr); field.setvalue(mystruct, structure); break; case fieldinfotype.fituint32: field.setvalue(mystruct, tr.readuint32()); break; case fieldinfotype.fituint32array1d: uint32[] = (uint32[])fieldval; (int = 0; < a.length; i++) { a[i] = tr.readuint32(); } field.setvalue(mystruct, a); break; case fieldinfotype.fituint32array2das1d: uint32[] ui32ary = (uint32[])fieldval; int ui32aryindex = 0; (int = 0; < fieldinfo._dim1; i++) { (int j = 0; j < fieldinfo._dim2; j++) { ui32ary[ui32aryindex++] = tr.readuint32(); } } field.setvalue(mystruct, ui16ary); break; case fieldinfotype.fitstruct2das1d: throw new notsupportedexception(); default: throw new exception("structure field " + field.name + "must have type"); } } } } } public static void structtostring<t>(t mystruct, textwriter tw) { foreach (var field in mystruct.gettype().getfields(bindingflags.instance | bindingflags.nonpublic | bindingflags.public)) { foreach (attribute attr in getcustomattributes(field)) { var fieldinfo = attr fieldinfo; if (fieldinfo != null) { var fieldval = field.getvalue(mystruct); switch (fieldinfo._type) { case fieldinfotype.fitstruct: tw.writeline("# {0}", fieldinfo._description); structtostring(field.getvalue(mystruct), tw); break; case fieldinfotype.fituint32: tw.writeline("0x{0:x8} \t# {1} - {2}", fieldval, field.name, fieldinfo._description); break; case fieldinfotype.fituint32array1d: uint32[] d = (uint32[])fieldval; (int = 0; < d.length; i++) { tw.writeline("0x{0:x8} \t# {1}[{2}]", d[i], field.name, i); } break; case fieldinfotype.fituint32array2das1d: uint32[] ui32ary = (uint32[]) fieldval; int ui16aryindex = 0; (int = 0; < fieldinfo._dim1; i++) { (int j = 0; j < fieldinfo._dim2; j++) { tw.writeline("0x{0:x4} \t# {1}[{2},{3}]", ui32ary[ui32aryindex++], field.name, i, j); } } break; case fieldinfotype.fitstruct2das1d: throw new notsupportedexception(); default: throw new exception("structure field " + field.name + "must have type"); } } } } } } public static class arrayop { public static void append<t>(ref t[] startingarray, t[] appendarray) { int startingarraysize = startingarray.length; array.resize(ref startingarray, startingarraysize + appendarray.length); buffer.blockcopy(appendarray, 0, startingarray, startingarraysize, appendarray.length); } public static t[] pack2darrayinto1darray<t>(t[,] input) { t[] result = new t[input.length]; int index = 0; (int = 0; < input.getlength(0); i++) { (int j = 0; j < input.getlength(1); j++) { result[index++] = input[i, j]; } } return result; } public static t[,] unpack1darrayinto2darray<t>(t[] input, int x, int y) { t[,] temp = new t[x, y]; int index = 0; (int = 0; < x; i++) { (int j = 0; j < y; j++) { temp[i, j] = input[index++]; } } return temp; } }
then, can declare structure follows
private int cost rows = 10; private int cost cols = 20; [structlayout(layoutkind.sequential, pack = 1), serializable] public class mystruct1 { [fieldinfo("my description of uint32 field", fieldinfotype.fituint32)] public uint32 a; [fieldinfo("my description of uint32[] field", fieldinfotype.fituint32array1d)] [marshalas(unmanagedtype.byvalarray, sizeconst = numparallaxspares)] public uint32[] b; [fieldinfo("my description of uint32[,] field", fieldinfotype.fituint32array2das1d, rows, cols)] [marshalas(unmanagedtype.byvalarray, sizeconst = (rows*cols))] private uint32[] _c; public uint32[,] c { { return arrayop.unpack1darrayinto2darray(_c, rows, cols); } set { _c = arrayop.pack2darrayinto1darray(value); } } }
everything above works expected. now, want stringify array of structs, so
[structlayout(layoutkind.sequential, pack = 1), serializable] public class mystruct2 { [fieldinfo("my description of uint32 field", fieldinfotype.fituint32)] public uint32 a; [fieldinfo("my description of uint32 field", fieldinfotype.fituint32)] public uint32 b; } [structlayout(layoutkind.sequential, pack = 1), serializable] public class mystruct3 { [fieldinfo("my description of mystruct2[,] field", fieldinfotype.fitstruct2das1d, rows, cols)] [marshalas(unmanagedtype.byvalarray, sizeconst = (rows*cols))] private mystruct2[] _c; public mystruct2[,] c { { return arrayop.unpack1darrayinto2darray(_c, rows, cols); } set { _c = arrayop.pack2darrayinto1darray(value); } } }
what right generic way handle in structtostring() , stringtostruct() functions? ideally, wind being recursive call same function each of elements within array, fieldinfotype.fitstruct attribute.
Comments
Post a Comment