Следующее использует Convert.ChangeType
для обеспечения большей гибкости с преобразованиями.
Код комментирует документ о том, что делается.
public object ConvertValue(object value, Type targetType){
var valueType = value.GetType();
// Func<TValue,TTarget>
var delegateType = typeof(Func<,>).MakeGenericType(valueType, targetType);
var convert = typeof(Convert).GetMethod("ChangeType", new[] { typeof(object), typeof(Type) });
// TValue p
var parameter = Expression.Parameter(valueType, "p");
// Convert.ChangeType(Convert(p), targetType);
var changeType = Expression.Call(convert, Expression.Convert(parameter, typeof(object)), Expression.Constant(targetType));
// (TTarget)Convert.ChangeType(Convert(p), targetType);
var body = Expression.Convert(changeType, targetType);
//Func<TValue,TTarget> = TValue p => (TTarget)Convert.ChangeType(Convert(p), targetType);
var lambda = Expression.Lambda(delegateType, body, parameter);
var method = lambda.Compile();
var result = method.DynamicInvoke(value);
return result;
}
Следующие базовые тесты все прошли, когдатренируется
[TestMethod]
public void Should_Convert_Int_To_Long() {
var expected = typeof(long);
var actual = ConvertValue(23, expected);
Assert.AreEqual(expected, actual.GetType());
}
[TestMethod]
public void Should_Convert_Long_To_Int() {
var expected = typeof(int);
var actual = ConvertValue((long)23, expected);
Assert.AreEqual(expected, actual.GetType());
}
[TestMethod]
public void Should_Convert_String_To_Long() {
var expected = typeof(long);
var actual = ConvertValue("23", expected);
Assert.AreEqual(expected, actual.GetType());
}
[TestMethod]
public void Should_Convert_String_To_Int() {
var expected = typeof(int);
var actual = ConvertValue("23", expected);
Assert.AreEqual(expected, actual.GetType());
}