如何<T>通过 FieldInfo.GetValue() 获取可为空值(而不是基础值)?



在一个应用程序中,我有一些代码,有一个FieldInfo为Nullable并且我需要检索可空值(而不是底层值),就像下面的示例一样:

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);
     }
 }

我的问题是v总是被赋给底层值(在这个示例中是int)而不是可空值(在这个示例中是Nullable)。

PS:实际应用程序在编译时没有可空类型,因此不可能进行强制类型转换。

提前感谢您的帮助。

本例中v的类型为object。如果value为空,则v为空;如果value是某个整数,那么v就是那个整数。如果您希望v实际上具有Nullable<int>类型,则必须这样声明:var v = (int?) fld.GetValue(obj); .

如果您需要能够引用v.Value并获得盒装值,您可能必须记录fld可为空(Nullable.GetUnderlyingType(fld.FieldType) != null)的事实。请注意,泛型在这里没有帮助,因为您在编译时不知道T

这里有一个你可以使用的帮助器:

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);
    }
}

然后不调用var v = fld.GetValue(obj);,说var v = fld.GetNullableValue(obj);。如果fld代表一个Nullable类型,你将得到一个具有Value属性的对象;

首先,您需要在PropertyInfo对象数组中获得"Test"类的所有属性。形成一个循环,调用每个PropertyInfo的"PropertyType"属性的"GetGenericTypeDefinition"方法,并将其与Nullable类型进行比较。还要检查它是否是泛型类型。如果两者都为真,则调用PropertyInfo的PropertyType属性的"GetGenericArguments"方法。这将返回一个"Type"对象数组。取它的第一个元素。这将是你需要的字体。

如果你有多个可空类型,那么你可以通过"PropertyInfo"获取属性的名称。

下面是代码,您可以根据自己的方便进行尝试和修改。

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];
                }
            }
        }
    }
}

相关内容

  • 没有找到相关文章

最新更新