12

我尝试动态设置 Nullable<> 属性。

我得到我的财产前:

PropertyInfo property = class.GetProperty("PropertyName"); // My property is Nullable<> at this time So the type could be a string or int

我想通过反射来设置我的属性,比如

property.SetValue(class,"1256",null);

当我的属性是 Nullable<> Generic 时,它不起作用。所以我试图找到一种方法来设置我的财产。

要知道我执行的 nullable<> 属性的类型

Nullable.GetUnderlyingType(property.PropertyType)

任何的想法 ?

  • 我尝试使用创建我的 Nullable<> 属性的实例

    var nullVar = Activator.CreateInstance(typeof(Nullable<>).MakeGenericType(new Type[] { Nullable.GetUnderlyingType(property.PropertyType) }));

但 nullVar 始终为 Null

4

6 回答 6

17

如果要将任意字符串转换为 Nullable 的基础类型,可以使用 Convert 类:

var propertyInfo = typeof(Foo).GetProperty("Bar");
object convertedValue = null;
try 
{ 
    convertedValue = System.Convert.ChangeType("1256", 
        Nullable.GetUnderlyingType(propertyInfo.PropertyType));
} 
catch (InvalidCastException)
{
    // the input string could not be converted to the target type - abort
    return;
}
propertyInfo.SetValue(fooInstance, convertedValue, null);

如果目标类型是 int、short、long(或无符号变体,因为输入字符串表示非负数)、double、float 或 decimal,则此示例将起作用。警告:这不是快速代码。

于 2009-09-28T19:02:46.253 回答
9

如果它是可为空的 int,则需要使用 int 参数,而不是字符串。

 property.SetValue(klass,1256,null);

请注意更改为 klass,而不是 class,因为 class 是保留关键字。如果绝对必要,您也可以使用@class(引用它)。

如果您的属性是通用属性,那么我认为您可能需要使用 Convert 将您拥有的任何内容转换为您需要的任何内容。

 var nullType = Nullable.GetUnderlyingType(property.PropertyType)
 var value = Convert.ChangeType("1256", nullType );
 property.SetValue(klass, value, null );
于 2009-09-28T18:50:34.453 回答
5

这是一个完整的示例,展示了如何执行此操作:

using System;
using System.Reflection;

class Test
{
    static void Main()
    {
        Foo foo = new Foo();
        typeof(Foo).GetProperty("Bar")
            .SetValue(foo, 1234, null);
    }
}

class Foo
{
    public Nullable<Int32> Bar { get; set; }
}

正如其他人所提到的,您需要将正确的类型传递给SetValue函数,但您的其他反射代码也不完全正确。您需要先获取相关类的类型,然后才能查询其成员。

编辑:如果我理解正确,您正在尝试通过反射将字符串值设置为任何属性。为此,您需要进行一些类型检查和类型转换。

这是我的意思的一个例子:

using System;
using System.Reflection;

class Test
{
    static void Main()
    {
        Foo foo = new Foo();

        PropertyInfo property = typeof(Foo).GetProperty("Bar");
        Object value =
            Convert.ChangeType("1234",
                Nullable.GetUnderlyingType(property.PropertyType)
                ?? property.PropertyType);

        property.SetValue(foo, value, null);
    }
}

class Foo
{
    public Nullable<Int32> Bar { get; set; }
}

无论属性是否为 ,都可以安全地使用这种方法Nullable<>

于 2009-09-28T18:53:14.167 回答
3

我遇到了同样的问题以及 Convert.ChangeType 未处理 Nullables 上的 DateTimes 的问题,因此我将一些 stackoverflow 解决方案与一些 .NET 4 动态魔法结合起来,以获得我认为有点甜的东西。如果您查看代码,我们在运行时使用动态将对象键入为 Nullable,然后运行时对其进行不同的处理,并允许将基类型分配给可为空的对象。

public void GenericMapField(object targetObj, string fieldName, object fieldValue)
{
    PropertyInfo prop = targetObj.GetType().GetProperty(fieldName);
    if (prop != null)
    {
        if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
        {
            dynamic objValue = System.Activator.CreateInstance(prop.PropertyType);
            objValue = fieldValue;
            prop.SetValue(targetObj, (object)objValue, null);
        }
        else
        {
            prop.SetValue(targetObj, fieldValue, null);
        }
    }
}
于 2011-10-26T10:55:12.497 回答
2

"1256"是一个字符串,而不是一个 int。

于 2009-09-28T18:51:04.770 回答
1
public static void SetValue(object target, string propertyName, object value)
{
  if (target == null)
    return;

  PropertyInfo propertyInfo = target.GetType().GetProperty(propertyName);

  object convertedValue = value;
  if (value != null && value.GetType() != propertyInfo.PropertyType)
  {
    Type propertyType = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType;
    convertedValue = Convert.ChangeType(value, propertyType);
  }

  propertyInfo.SetValue(target, convertedValue, null);
}
于 2014-04-26T07:57:37.430 回答