2

在一个应用程序中,我有一些代码具有 Nullable<int> 的 FieldInfo,我需要检索可空值(而不是基础值),如下面的示例所示:

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<int>)。

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

提前感谢您的帮助。

4

2 回答 2

4

在这种情况下v是类型object。如果value为空,则为v空;如果value是某个整数,那么v将是那个整数。如果您想v实际拥有该类型,Nullable<int>则必须将其声明为:var v = (int?) fld.GetValue(obj);.

如果您需要能够引用v.Value并取回装箱的值,您可能必须记录可以fld为空的事实 ( Nullable.GetUnderlyingType(fld.FieldType) != null)。请注意,泛型在这里对您没有帮助,因为您不知道Tat compile time。

这是您可以使用的助手:

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属性的对象;如果没有,您将获得价值。

于 2011-11-22T01:36:33.730 回答
0

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

如果您有多个可为空的类型,那么您可以通过“PropertyInfo.Name”获取属性的名称并进行相应的比较。

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

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

}
于 2011-11-23T05:28:52.680 回答