我使用下面的代码设置类的值,此类的一些值为string
decimal
decimal?
int?
等。
我有一个字段列表 - 其值为字符串,.net正在抛出以下异常:
System.InvalidCastException : Invalid cast from 'System.String' to 'System.Nullable`1[[System.Decimal, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'.
at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
at System.String.System.IConvertible.ToType(Type type, IFormatProvider provider)
at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
at System.Convert.ChangeType(Object value, Type conversionType)
at Surventrix.Domain.Model.Entities.StatisticalData.UpdateStatisticalData(ReportCommit commit, ILogProvider log) in StatisticalData.cs: line 591
at Surventrix.Tests.Stats.StatsTest.CreateStatsFromCommit() in StatsTest.cs: line 32
我的代码是:
public void UpdateStatisticalData(ReportCommit commit, ILogProvider log)
{
var fields = commit.CurrentFieldList.ToList();
var properties = typeof(StatisticalData).GetProperties();
foreach (var p in properties)
{
log.LogMessage("what my name: {0}", p.Name);
// If not writable then cannot null it; if not readable then cannot check it's value
if (!p.CanWrite || !p.CanRead) { continue; }
var mget = p.GetGetMethod(false);
var mset = p.GetSetMethod(false);
// Get and set methods have to be public
if (mget == null) { continue; }
if (mset == null) { continue; }
var val = fields.SingleOrDefault(x => p.Name == x.Name);
if (val == null) continue;
//field.value is stored as a string
if (string.IsNullOrEmpty(val.Value)) continue;
log.LogMessage("set: {0} ----> {1}", p.Name, val.Value);
var typedVal = Convert.ChangeType(val.Value, p.PropertyType);
p.SetValue(this, typedVal, null);
}
}
问题:我如何修复我的代码以便不抛出此异常,我真的不明白为什么这个异常被抛出......
更新 - 日志结果 *
what my name: StatisticalDataID
what my name: OfficeDistanceFromProperty
what my name: OfficeAddress1
set: OfficeAddress1 ----> North Warwickshire House
what my name: OfficeAddress2
set: OfficeAddress2 ----> 92 Wheat Street
what my name: OfficeAddress3
what my name: OfficeCounty
what my name: OfficeTown
set: OfficeTown ----> Nuneaton
what my name: OfficePostcode
set: OfficePostcode ----> CV11 4BH
what my name: ResidentialInternalFloorArea
what my name: ValuationCalculationSqFtAssumed
what my name: SubjectPropertyAddress1
set: SubjectPropertyAddress1 ----> 323 Stanton road
what my name: SubjectPropertyAddress2
set: SubjectPropertyAddress2 ----> cbvcb
what my name: SubjectPropertyAddress3
set: SubjectPropertyAddress3 ----> vcbc
what my name: SubjectPropertyTown
set: SubjectPropertyTown ----> Coventry
what my name: SubjectPropertyCounty
set: SubjectPropertyCounty ----> bcbvc
what my name: SubjectPropertyPostCode
set: SubjectPropertyPostCode ----> CV1 4HH
what my name: OccupierName
set: OccupierName ----> Mr Peters
what my name: AdvanceAmount
set: AdvanceAmount ----> 0
更新 - 我已更新到您的代码@Jon,我正在调用这样的方法:
var typedVal = NullableSafeChangeType(val.Value, p.PropertyType);
if (!string.IsNullOrEmpty(val.Value))
p.SetValue(this, typedVal, null);
在以下位置引发错误:
_log.LogMessage("error is here ---> {0}", input);
return input == null || input == "" ? null : Convert.ChangeType(input, underlyingType);
输入是任何有效的字符串,类型(System.String)
答案 0 :(得分:5)
它与设置属性无关,而与更改类型有关。这是一个简短而完整的例子,展示了这个问题:
using System;
class Test
{
static void Main()
{
object converted = Convert.ChangeType("10", typeof(int?));
Console.WriteLine(converted);
}
}
基本上,Convert.ChangeType
不支持Nullable<T>
。你必须自己处理。您可以编写一个方法来检测目标类型是Nullable<T>
,并返回null(如果原始字符串值为null或对空字符串的引用)或将其转换为基础类型的结果。< / p>
编辑:例如(完全未经测试):
static object NullableSafeChangeType(string input, Type type)
{
Type underlyingType = Nullable.GetUnderlyingType(type);
if (underlyingType == null) // Non-nullable; convert directly
{
return Convert.ChangeType(input, type);
}
else
{
return input == null || input == "" ? null
: Convert.ChangeType(input, underlyingType);
}
}
答案 1 :(得分:0)
我认为您需要以下方法:
private static T Convert<T>(string input)
{
if (input == null) throw new ArgumentNullException("input");
var converter = TypeDescriptor.GetConverter(typeof(T));
if (input.Is(typeof(T)))
{
try
{
return (T)converter.ConvertFromString(input);
}
catch (NotSupportedException notSupportedException)
{
Console.WriteLine(notSupportedException);
}
}
return default(T);
}
使用:
try
{
// If Value is not a string => Convert over Generic Method
MethodInfo method = typeof(whereConvertImplemented).GetMethod("Convert", BindingFlags.NonPublic | BindingFlags.Static);
MethodInfo generic = method.MakeGenericMethod(property.PropertyType);
var value = generic.Invoke(this, new object[] { propvalue });
property.SetValue(this, value, null);
}
catch
{
}
希望它适合你:)
问候
答案 2 :(得分:0)
这一行
var typedVal = Convert.ChangeType(val.Value,p.PropertyType);
不适用于可空类型。您已为可为空类型的属性类型添加特殊情况,如果值为null或为空,则将属性值设置为null。