Reflections Reihenfolge GetFields/GetProperties



  • Hallo Leute,

    ich hab mal ne Frage:) Ich habe gelesen, dass nich gewährleistet ist, dass die Reihenfolge des Members/Feldert welche ich via Refl. ermittle nicht der Reihenfolge entsprechen in der sie deklariert sind. (verwendet Net4.0 VS2010)

    Ab .NET 4.5 soll es ja über LineNumber Attribute getrickst möglich sein (Hab ich so überfliegend gelesen)

    Dann hab ich paar tests, gemacht aber bisher war die Reihenfolge immer richtig.. hmm..

    Aber wie macht es Marshal beim Mappen von bytes in Strukturen etc. das dürfte ja dann auch nich safe sein oder.. also die Member-Order etc. !

    Grüße und ein schönes WE;)



  • Hallo ,

    nach bissel recherche, hab ich glaub paar Möglichkeiten Workarounds gefunden.

    (A)

    So soll der Wert des MetadatToken entsprechend der Reihenfolge steigen hmm

    IEnumerable<FieldInfo> orderedFields = test.GetFields()
    											 .OrderBy(field =>	field.MetadataToken)
    											 .ToList();
    

    (B)
    Bei verwendung von strukturen kann man Marshal zur hilfe ziehn (bevorzugte Variante)

    IEnumerable<FieldInfo> orderedFields = test.GetFields().OrderBy(f => Marshal.OffsetOf(test, f.Name).ToInt32()).ToList();
    

    was meint ihr?;) 😃



  • Ich kann dir nicht folgen. Welche Relevanz hat denn die Reihenfolge für den Zugriff via Reflection?

    Mir wäre es neu per Indexer irgendwas mit Reflection zu werkeln. Im Normalfall weiß man, welchen Member man manipulieren will.

    Da ist es doch egal, dass die Methode GetFields die Member unsortiert auf Basis irgendwelcher internen Regeln zurück liefert. Hauptsache die Felder werden geliefert.



  • Ich will Datenstrukturen eines externe Systems (SPS) auf Strukturen in der .NET Domain "mappen". in dem Fall bilde ich die Strukturen(1:1) ab und mappe die bytehaufen.. da muss gewährleistet sein, dass ich die Felder in richtiger Reihfolge (offest) bekomme...



  • Wenn das PODs sind, macht die Marshal Klasse das für dich richtig.



  • Moment mal, wozu genau brauchst du da jetzt Reflection?!



  • Hmm.. es sind POD's => Beckhoff! Beckhofe verwendet 8 Byte Struct Aligment!

    Habe auch schon die strukturen nach gebaut und mit Marshal (Sizeof) evaluiert, aber es kommen andere größen raus wie in Beckhof!

    http://infosys.beckhoff.de/english.php?content=../content/1033/tcplclibsystem/html/TcPlcLibSys_F_GetStructMemberAlignment.htm&id=

    Reflections hab ich deshalb gebraucht, weil wohl die Marshalklasse und StructLayout sich nich so verhält wie es Beckhof macht, und ich das Datenmodel analysieren musste!! und entsprechedne Padding bytes (offset) setzen



  • .NET verwendet soweit ich weiss auch per Default 8 Byte Alignment. Kannst du aber alles kontrollieren, da gibt es Attributes dafür.
    z.B. StructLayoutAttribute
    https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.structlayoutattribute(v=vs.100).aspx?f=255&MSPPError=-2147217396

    Als Notlösung kannst du sogar auf "manuell" umschalten und jeden Offset selbst eingeben. Irgendwas über Reflection zu machen ist also ziemlich sicher nicht nötig.



  • @hustbear: Ja das mit structLayout etc. hab ich schon probiert und Pack=8 etc. aber leider kommen andere größen raus wie auf Beckhoff... siehe Link!

    Aber ich hab jetzt ne andere Möglichkeit gefunden, Die Symbolstruktur der SPS auszulesen, über dies kann ich dann die Daten easy mappen.. glaub ich;)

    Danke euch



  • Was für größen haben die Werte denn in der Beckhoff SPS und was für größen in deinem Struct? Im Zweifel ist eventuell nur der falsche Typ im Struct verwendet?



  • NullBockException schrieb:

    @hustbear: Ja das mit structLayout etc. hab ich schon probiert und Pack=8 etc. aber leider kommen andere größen raus wie auf Beckhoff... siehe Link!

    Glaub ich nicht.
    Zeig ein Beispiel.



  • TYPE ST_A1
    STRUCT
    ui8 : BYTE := 16#FF;(* FF )
    ui32 : DWORD := 16#AABBCCDD;(
    DD CC BB AA )
    rsv : BYTE := 16#EE;(
    EE 😉
    END_STRUCT
    END_TYPE

    TYPE ST_A2
    STRUCT
    ui16 : WORD := 16#1234;(* 34 12 )
    ui8 : BYTE := 16#55;(
    55 😉
    END_STRUCT
    END_TYPE

    TYPE ST_TEST4
    STRUCT
    a1 : ST_A1;
    a2 : ST_A2;
    END_STRUCT
    END_TYPE
    test4 : ST_TEST4;

    test4 => 16 Beckhoff
    test4=> 14 .NET



  • struct Test11
    	{
    		public int[, ,] Fields;
    	}
    
    	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)]
    	[AdsStructure]
    	struct ST_A1
    	{
    		public byte ui8;
    		public int ui32;
    		public byte res;
    	}
    
    	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)]
    	[AdsStructure]
    	struct ST_A2
    	{
    		public short ui16;
    		public int ui8;
    	}
    	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)]
    	[AdsStructure]
    	struct ST_TEST4
    	{
    		public ST_A1 a1;
    		public ST_A2 a2;
    	}
    

    sorry .NET => 20



  • Vielleicht verwendest du wie ich sagte einfach die falschen .NET Typen. Ein Beispiel:

    TYPE ST_A1
    STRUCT
    ui8 : BYTE := 16#FF;(* FF *)
    ui32 : DWORD := 16#AABBCCDD;(* DD CC BB AA *)
    rsv : BYTE := 16#EE;(* EE *)
    END_STRUCT
    END_TYPE
    

    Hier müssten im Struct die Typen byte und uint verwendet werden.

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)]
    [AdsStructure]
    struct ST_A1
    {
        public byte ui8;
        public uint ui32;
        public byte res;
    }
    

    EDIT: Weil mir gerade dannach ist für das andere Struct hier auch noch:

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 8)]
    [AdsStructure]
    struct ST_A2
    {
        public ushort ui16;
        public byte ui8;
    }
    

    Nach den Anpassungen bekomme ich mit

    ST_TEST4 test = new ST_TEST4();
    Marshal.SizeOf(test);
    

    den Wert 16.

    Und für weitere Informationen zu den Datentypen: Vergleich Datentypen



  • Naja wenn man nicht auf den 1. Blick sieht dass bei int ui8 was nicht stimmen kann, dann bekommt man natürlich Blödsinn raus. GIGO halt.



  • Fuck man.. :(( Wieso hab ich das übersehen.. Danke Dir:)


Anmelden zum Antworten