在一个应用程序中,我有一些代码,有一个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];
}
}
}
}
}