Wie bekomme ich einen Nullwert <T> (anstelle des zugrunde liegenden Werts) durch FieldInfo.GetValue ()

  • In einer Anwendung habe ich Code, der eine FieldInfo für eine Nullable & lt; int & gt; und ich muss den nullfähigen Wert (nicht den zugrunde liegenden Wert) wie im folgenden Beispiel abrufen:

     class Test
    {
        public int? value;
    }
    
    public class Program
    {
        static void Main(string[] args)
        {
            var obj = new Test { value = 10 };
            var fld = typeof (Test).GetField("value");
            var v = fld.GetValue(obj);
    
            System.Diagnostics.Debug.WriteLine(v.GetType().FullName);
            System.Diagnostics.Debug.WriteLine(fld.FieldType.FullName);
         }
     }
     

    Mein Problem ist, dass v immer der zugrunde liegende Wert (in diesem Beispiel ein int ) anstelle der Nullwerte (in diesem Beispiel ein Nullable & lt; int & gt;) zugewiesen wird.

    PS: Die reale Anwendung hat zur Kompilierzeit nicht den Typ der Nullwerte, daher ist kein Cast möglich.

    Vielen Dank im Voraus Hilfe.

    22 November 2011
    Vagaus
2 answers
  • In diesem Fall ist v vom Typ object. Wenn value Null ist, ist v Null. Wenn value eine ganze Zahl ist, ist v diese ganze Zahl. Wenn Sie möchten, dass v tatsächlich den Typ Nullable<int> hat, müssen Sie ihn als solchen deklarieren: var v = (int?) fld.GetValue(obj);.

    Wenn Sie auf v.Value und den Boxwert zurückbekommen, müssen Sie wahrscheinlich festhalten, dass fld nullbar war (Nullable.GetUnderlyingType(fld.FieldType) != null). Beachten Sie, dass Generics Ihnen hier nicht weiterhelfen werden, da Sie T zur Kompilierzeit nicht kennen.

    Hier können Sie einen Helfer verwenden:

     struct NullableObject
    {
        public object Value { get; private set; }
    
        public static object GetField(object Target, FieldInfo Field)
        {
            object value = Field.GetValue(Target);
            if (Nullable.GetUnderlyingType(Field.FieldType) != null)
                return new NullableObject { Value = value };
            return value;
        }
    }
    
    public static class NullableHelper
    {
        public static object GetNullableValue(this FieldInfo field, object target)
        {
            return NullableObject.GetField(target, field);
        }
    }
     

    Dann rufen Sie statt var v = fld.GetValue(obj); var v = fld.GetNullableValue(obj); an. Wenn fld einen Nullable-Typ darstellt, erhalten Sie ein Objekt mit der Eigenschaft Value. Andernfalls erhalten Sie nur den Wert.

    22 November 2011
    Gabe
  • Zuerst müssen Sie alle Eigenschaften der Klasse "Test" in einem Array von PropertyInfo-Objekten abrufen. Bilden Sie eine Schleife, rufen Sie die "GetGenericTypeDefinition" -Methode der "PropertyType" -Eigenschaft jedes PropertyInfo-Objekts auf und vergleichen Sie sie mit dem Nullable-Typ. Prüfen Sie auch, ob es sich um einen generischen Typ handelt. Wenn beide wahr sind, rufen Sie die Methode "GetGenericArguments" der Eigenschaft "PropertyType" dieser PropertyInfo auf. Dies gibt ein Array von "Type" -Objekten zurück. Nimm das erste Element. Dies ist Ihr erforderlicher Typ.

    Wenn Sie mehrere nullfähige Typen haben, können Sie den Namen der Eigenschaft über "PropertyInfo.Name" abrufen und entsprechend vergleichen.

    Nachfolgend finden Sie den Code, den Sie je nach Ihren Wünschen ausprobieren und ändern können:

     using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Reflection;
    
    namespace Nullable_Demo
    {
        class Test
        {
            public int? value { get; set; }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                var obj = new Test { value = 10 };
                //var fld = typeof(Test).GetField("value");
                //var v = fld.GetValue(obj);
    
                Type typeobjs = obj.GetType();
                PropertyInfo[] piObjs = typeobjs.GetProperties();
    
                foreach (PropertyInfo piObj in piObjs)
                {
                    Type typeDefinedInNullable;
    
                    // Test for Nullable
                    bool isNullable = piObj.PropertyType.IsGenericType &&
                        piObj.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>);
    
                    if (isNullable)
                    {
                        // Returns the basic data type without reference to Nullable (for example, System.Int32)
                        typeDefinedInNullable = piObj.PropertyType.GetGenericArguments()[0];
                    }
                }
            }
        }
    
    }
     
    06 June 2012
    Seph