基本的に、私は使用しようとしています
field.SetValue(obj, val);
Whereval
の型は、真のフィールド型に暗黙的に変換できますが、「直接」割り当て可能ではありません。もちろん、私はいつものArgumentException: Object type cannot be converted to target type
. コンストラクターを手動で見つけて呼び出さずにこれを行う方法はありますか?
基本的に、私は使用しようとしています
field.SetValue(obj, val);
Whereval
の型は、真のフィールド型に暗黙的に変換できますが、「直接」割り当て可能ではありません。もちろん、私はいつものArgumentException: Object type cannot be converted to target type
. コンストラクターを手動で見つけて呼び出さずにこれを行う方法はありますか?
これは非常に複雑な質問であり、1 行で機能させる方法がわかりません。単純なケースでは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);
}
}