2009-09-28 64 views
10

我尝试动态设置Nullable <>属性。通过反射设置属性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.GetUnderlyingType(property.PropertyType) 

任何想法,我可空<>属性的类型?

  • 我尝试创建我可空<>属性的实例与

    VAR nullVar = Activator.CreateInstance(typeof运算(可空<>)。MakeGenericType(新类型[] {Nullable.GetUnderlyingType(财产。财产种类) }));

但nullVar总是空

+0

当您设置一个整数,而不是字符串是否行得通? '“1256”是一个字符串,不是一个整数。 – 2009-09-28 18:51:13

+0

它会工作,但重点是我不知道可空属性的类型。我可以使用Nullable.GetUnderlyingType(property.PropertyType)获得类型 – 2009-09-28 18:57:09

+0

'Nullable <>'不能使用'string'作为基础类型,因为'string'是一个引用类型。换句话说'typeof(Nullable <>)。MakeGenericType(t);'如果使用't == typeof(int)''会很好,但是会爆炸(不符合约束)'t == typeof(string) 。所以'Nullable <>'不会以任何方式作为参考类型和可为空值类型的一种“通用类型”。 – 2017-10-04 20:27:11

回答

13

如果你想的任意字符串转换为基本类型的可空的,你可以使用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,短,长的这个例子就可以了(或无符号变量,因为输入字符串表示非负数),double,float或decimal。警告:这不是快速的代码。

+0

我会尝试,在这个时候我叮叮当当你是我接近的答案我搜索 – 2009-09-28 19:07:51

+0

它的工作感谢 – 2009-09-28 19:11:57

+0

它的工作谢谢你 – 2013-09-23 11:46:47

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); 
+0

我知道这是一个字符串,但它是通用的,所以我不知道会是什么类型。这只是一个例子,我的genric Nullable <>可能是一个字符串,int一般的转换将会完成 – 2009-09-28 18:53:55

+2

由于'string'不是一个值类型,所以你不能有一个'Nullable '。 – 2009-09-28 18:55:42

2

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

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<>可以安全使用。

2

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