我有以下界面:
public interface IDynamicData: IPersistent
{
string Name { get; }
DataType Type { get; set; }
string InputFormat { get; set; }
dynamic Value { get; }
string DisplayValue { get; }
}
我有几个实现此接口的类,但我感兴趣的是这个:
public class DynamicInput : IDynamicData
{
public string Name { get; private set; }
private DataType _Type;
public DataType Type
{
get { return _Type; }
set
{
_Type = value;
switch (Type)
{
case DataType.String:
Mapping = new StringMap();
break;
case DataType.Numeric:
Mapping = new DoubleMap();
break;
case DataType.DateTime:
Mapping = new DateTimeMap();
break;
default:
Mapping = new StringMap();
break;
}
}
}
[Browsable(false)]
public dynamic Value { get; private set; }
[Browsable(false)]
public string DisplayValue
{
get
{
return Value != null && (Type.Equals(DataType.DateTime) || Type.Equals(DataType.Numeric))
? Value.ToString(InputFormat)
: Value;
}
}
}
现在,关键是dynamic Value
属性。使用StringMap
,DecimalMap
,DoubleMap
和DateTimeMap
类从字符串输入填充此值,其中键方法(类似于)此类:
public override dynamic ProcessInput(string input, int index, string inputFormat, double multiplier, char splitOn = ',')
{
_IsValid = false;
try
{
_Input = input;
double tmp;
_IsValid = Double.TryParse(input.Split(splitOn)[index], out tmp);
return tmp * multiplier;
}
catch
{
_IsValid = false;
return 0;
}
}
这看起来很好用,我在运行时实际上有一个强类型Value
属性(至少我理解它)。我想知道何时出现这种类型的定义 - 实例化对象时,或者Value
被分配给。{/ p>
我希望能够让用户在运行时更改Value
属性的类型,这涉及将DataType
属性设置为string
/ DateTime
/ double
等。但是,这有时会导致在运行时抛出RuntimeBindingException
。它不会一直发生,只是有时候,我假设在DataType
属性被设置的Value
属性和正在读取的DisplayText
属性之间发生变化时发生。这就是错误发生的地方,在这个getter中:
public string DisplayValue
{
get
{
return Value != null && (Type.Equals(DataType.DateTime) || Type.Equals(DataType.Numeric))
? Value.ToString(InputFormat)
: Value;
}
}
我只想了解为什么会发生这种情况,以及我的分析是否正确,以及可能是否存在此问题的解决方法。如果它不可能那么没关系,我将锁定IDynamicData对象类型的编辑。
修改
我只经历了一次 - 难以复制。实例是,该对象是使用DataType.Numeric
创建的。我输入了像“12.345”这样的字符串,每秒都被解析然后分配给Value
属性。然后,当我仍在接收数据时,我改为DataType.String
。这是异常发生的地方。也就是说,DoubleMap
返回“动态”double
,然后当输入数据仍然存在时,StringMap
返回“动态”string
表示“12.345”
答案 0 :(得分:1)
我怀疑你有一个值,如字符串“15”,但Type属性设置为,例如,DataType.Numeric。在这种情况下,您的代码将尝试调用ToString()的参数化重载。因为接收对象是一个字符串,所以没有这样的重载,因此绑定器会抛出异常。
这有点推测。如果你可以发布一个演示问题的工作示例,或者至少描述抛出异常时使用的特定值,我们可以更确定它的原因。
如果要将数字的字符串表示形式转换为该数字的int或double表示形式,则需要转换Value属性中的实际值。 (顺便说一下,属性的实际类型是对象,因此这里存储的值路由将被装箱。)对此最好的解决方案在某种程度上取决于您希望调用代码的外观。
编辑以响应您的编辑:另一种可能性是Value对象是数字数据类型,例如double,但Type属性是DataType.String。在这种情况下,您的代码会尝试直接返回double,这会导致binder失败,就像
一样string s = 1.2
会编译。在这种情况下,您可以使用ToString(),因此:
return Value != null && (Type.Equals(DataType.DateTime) || Type.Equals(DataType.Numeric))
? Value.ToString(InputFormat)
: Value.ToString();
然而,这更像是一种解决方法,而不是一种解决方案。我会检查对象的运行时类型并删除Type属性。