[.NET] FieldInfo.GetValue() retourneert null

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Topicstarter
Omdat de .NET XML serializer nogal moeilijk om kan met interfaces ben ik bezig om in een quickie een eenvoudige serializer te maken die voldoet aan mijn beperkte requirements.
Zoals de meeste serializers gebruik ik reflection om mijn objecten te ondervragen. Het probleem is echter dat de GetValue() functie van FieldInfo nogal stug null blijft retourneren.
Met de debugger zie ik echter dat het object wel degelijk een correct ingevulde member heeft. Het is ook al voorgekomen dat door in de debugger te retryen, plots geen null teruggegeven wordt en de code alsnog verder kan. Ik dacht dan ook aan een security issue, maar na invoegen van de ReflectionPermission lukt de code nog steeds niet. Ik heb met System.Security.SecurityManager.IsGranted() gecontroleerd dat de permission toegekend is.
Ik heb al even met .NET Reflector in mscorlib gezocht, maar kom op een dood spoor bij RunTimeFieldHandle.GetValue() (is extern geimplementeerd)
Google en het forum vinden mijn probleem ook niet, dus zit ik even op een dood spoor.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
[System.Security.Permissions.ReflectionPermission(
    System.Security.Permissions.SecurityAction.Assert,
    Flags=System.Security.Permissions.ReflectionPermissionFlag.AllFlags
              | System.Security.Permissions.ReflectionPermissionFlag.RestrictedMemberAccess)]
public class XmlSerializer
{
  protected void Serialize(XmlDocument doc, XmlNode parent, FieldInfo field, object o)
  {
    // ...
    doc.CreateTextNode(field.GetValue(o).ToString()); // GetValue() returns null
    // ...
  }
  protected void Serialize(XmlDocument doc, XmlNode parent, string name, object o)
  {
    // ...
    foreach (FieldInfo field in 
                       t.GetFields(BindingFlags.Instance | BindingFlags.GetField | BindingFlags.NonPublic 
                                 | BindingFlags.Public | BindingFlags.SetField | BindingFlags.IgnoreCase))
    {
                        Serialize(doc, node, field, o);
    }
    // ...
  }
  public void Serialize(string file, System.Collections.IEnumerable objects)
  {
    System.Security.Permissions.ReflectionPermission permission = 
       new System.Security.Permissions.ReflectionPermission(
                  System.Security.Permissions.PermissionState.Unrestricted);
    permission.Flags = System.Security.Permissions.ReflectionPermissionFlag.AllFlags 
            | System.Security.Permissions.ReflectionPermissionFlag.RestrictedMemberAccess;
    permission.Assert();
    // ...
    Serialize(doc, node, "object", o);
    // ...
  }
}


edit: mogelijk ook van belang: sommige members worden wel goed behandeld (vb. DateTime, int, ...) . Het type van de member waar de code nu faalt is List<Dependency> waar Dependency een klasse in mijn assembly is. Zou het aan ValueType <-> Reference Type liggen?

Iemand enig idee waarom GetValue() steeds null teruggeeft?

[ Voor 4% gewijzigd door H!GHGuY op 27-10-2009 10:56 ]

ASSUME makes an ASS out of U and ME


Acties:
  • 0 Henk 'm!

  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
Het soms wel/soms niet gedrag kan bijvoorbeeld duiden op andere threads die in je data lopen rommelen, of andere omgevingsfactoren waar je niet direct aan zou denken. Probeer hetgeen wat je wilt bereiken anders eerst eens uit zonder de rest van je applicatie eromheen, maar gewoon in een simpel console-appje.

De volgende code:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using System;
using System.Collections.Generic;
using System.Reflection;

namespace ReflectionTest
{
    public class Dependency
    {
        public int ID { get; set; }

        public Dependency(int id)
        {
            ID = id;
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            List<Dependency> dependencies = new List<Dependency>() { new Dependency(1), new Dependency(4) };
            DisplayContents(dependencies);

            Console.WriteLine("Press enter to exit...");
            Console.ReadLine();
        }

        public static void DisplayContents(object obj)
        {
            BindingFlags flags = BindingFlags.Instance | BindingFlags.GetField | BindingFlags.NonPublic
                                 | BindingFlags.Public | BindingFlags.SetField | BindingFlags.IgnoreCase;

            foreach (FieldInfo fieldInfo in obj.GetType().GetFields(flags))
                Console.WriteLine("Field name = \"{0}\", value = \"{1}\".", fieldInfo.Name, fieldInfo.GetValue(obj));
        }
    }
}

...levert bijvoorbeeld als output op:
code:
1
2
3
4
5
Field name = "_items", value = "ReflectionTest.Dependency[]".
Field name = "_size", value = "2".
Field name = "_version", value = "2".
Field name = "_syncRoot", value = "".
Press enter to exit...

Is dit ook wat je zou verwachten, of ben je bijvoorbeeld vergeten om IEnumerable ondersteuning te implementeren, of...?

Zorg in ieder geval dat je het "droog" kunt testen :)

Acties:
  • 0 Henk 'm!

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Topicstarter
De code wordt uitgevoerd zonder dat de rest van mijn applicatie draait. Ik heb enkel nog maar mijn datastore geopend en probeer die voor de GUI opent, of er een andere actie gebeurt te exporteren naar XML.

Je doet me er wel aan denken dat mijn datastore lazy activation ondersteunt... Eens zien of dat niet het probleem oplost.

edit:
Thx MrBucket.
De objecten waren niet geactiveerd. Aangezien je met reflection geen activation triggert (en met de debugger wel) kreeg ik dus het vreemde gedrag. Door de objecten nu op voorhand te activeren doet de code het wonderwel.

[ Voor 27% gewijzigd door H!GHGuY op 28-10-2009 08:40 ]

ASSUME makes an ASS out of U and ME