设置属性Nullable<>通过反思

时间:2009-09-28 18:47:53

标签: c# generics reflection nullable activator

我尝试设置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&lt;&gt;时,它无效通用。所以我试图找到一种方法来设置我的财产。

要知道我的可空类型&lt;&gt;属性我执行

Nullable.GetUnderlyingType(property.PropertyType)

有什么想法吗?

  • 我尝试创建一个Nullable&lt;&gt;的实例财产

    var nullVar = Activator.CreateInstance(typeof(Nullable&lt;&gt;)。MakeGenericType(new Type [] {Nullable.GetUnderlyingType(property.PropertyType)}));

但是nullVar总是空的

6 个答案:

答案 0 :(得分:16)

如果要将任意字符串转换为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,则此示例将起作用。警告:这不是快速代码。

答案 1 :(得分:9)

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

 property.SetValue(klass,1256,null);

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

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

 var nullType = Nullable.GetUnderlyingType(property.PropertyType)
 var value = Convert.ChangeType("1256", nullType );
 property.SetValue(klass, value, null );

答案 2 :(得分: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<>,都可以安全地使用此方法。

答案 3 :(得分:2)

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

答案 4 :(得分:2)

我遇到了同样的问题以及Convert.ChangeType没有在Nullables上处理DateTimes的问题所以我将一些stackoverflow解决方案与一些.NET 4动态魔术相结合,以获得我认为有点甜的东西。如果查看代码,我们使用dynamic在运行时将对象键入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);
        }
    }
}

答案 5 :(得分:0)

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