基本上,我正在尝试使用
field.SetValue(obj, val);
其中val
的类型可以隐式转换为真实字段类型,但不能“直接”分配。当然,我得到了通常的ArgumentException: Object type cannot be converted to target type
。有没有办法在不手动查找和调用构造函数的情况下执行此操作?
答案 0 :(得分:2)
尝试使用Convert.ChangeType:
field.SetValue(obj, Convert.ChangeType(val, field.PropertyType), null);
请查看以下Setting a property by reflection with a string value以获取更多信息。
答案 1 :(得分:2)
这是一个非常复杂的问题,我不知道如何让它在一条线上工作。虽然Convert.ChangeType
适用于简单的情况,但在以下情况下会失败:
目标类型是Nullable枚举,您使用整数值(不是枚举值):在这种情况下,您需要使用Enum.ToObject
来使其工作。
你的值是DBNull.Value:你需要测试它并在那种情况下指定null
目标类型与您要设置的值的数字类型不同:Convert.ChangeType
将在此为您提供帮助。
以下是一个说明如何操作的示例:
public void SetFieldValue(FieldInfo field, object targetObj, object value)
{
object valueToSet;
if (value == null || value == DBNull.Value)
{
valueToSet = null;
}
else
{
Type fieldType = field.FieldType;
//assign enum
if (fieldType.IsEnum)
valueToSet = Enum.ToObject(fieldType, value);
//support for nullable enum types
else if (fieldType.IsValueType && IsNullableType(fieldType))
{
Type underlyingType = Nullable.GetUnderlyingType(fieldType);
valueToSet = underlyingType.IsEnum ? Enum.ToObject(underlyingType, value) : value;
}
else
{
//we always need ChangeType, it will convert the value to the proper number type, for example.
valueToSet = Convert.ChangeType(value, fieldType);
}
}
field.SetValue(targetObj, valueToSet);
}
该功能的单元测试:
enum TestEnum
{
DummyValue
}
class TestClass
{
public int IntValue;
public decimal DecimalValue;
public int? NullableInt;
public TestEnum EnumValue;
public TestEnum? NullableEnumValue;
public TestClass ObjectValue;
}
[TestFixture]
public class DataObjectBinderFixture
{
private TestClass _testObject;
private void SetFieldValue(string fieldName, object value)
{
var fieldInfo = typeof (TestClass).GetField(fieldName);
ReflectionUtils.SetFieldValue(fieldInfo, _testObject, value);
}
[Test]
public void TestSetValue()
{
_testObject = new TestClass();
SetFieldValue("IntValue", 2.19);
SetFieldValue("IntValue", DBNull.Value);
SetFieldValue("DecimalValue", 1);
SetFieldValue("NullableInt", null);
SetFieldValue("NullableInt", 12);
SetFieldValue("EnumValue", TestEnum.DummyValue);
SetFieldValue("EnumValue", 0);
SetFieldValue("NullableEnumValue", TestEnum.DummyValue);
SetFieldValue("NullableEnumValue", null);
SetFieldValue("NullableEnumValue", 0);
SetFieldValue("NullableEnumValue", DBNull.Value);
SetFieldValue("ObjectValue", DBNull.Value);
}
}