Ceci est une question assez compliquée, et je ne connais pas un moyen de le faire fonctionner dans une ligne de sigle. Alors que les Convert.ChangeType
œuvres pour les cas simples, il échouera dans les cas suivants:
Le type de cible est un ENUM Nullable, et que vous utilisez une valeur entière (et non une valeur ENUM): dans ce cas, vous J'ai besoin d'utiliser Enum.ToObject
pour le faire fonctionner.
Votre valeur est DBNull.Value: Vous aurez besoin de le tester et affecter null dans ce cas
Le type de cible n'est pas le même type de numéro que la valeur que vous souhaitez définir: Convert.ChangeType
aidera vous ici.
Voici un exemple qui illustre comment le faire:
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);
}
Un test unitaire pour la fonction:
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);
}
}
J'ai essayé, mais je l'avais alors besoin de mettre en œuvre IConvertible interfaces, que je pouvais faire, mais j'essaie de trouver une autre façon –