![](/img/trans.png)
[英]How to call TypeConverter.ConvertTo or ConvertToString with InvariantCulture but without implementing ITypeDescriptorContext
[英]“Specified cast is not valid” error in TypeConverter.ConvertTo
我正在为Winform程序进行控制,并且在保存测试表单时会发生此错误。
这是解决方案结构,控件库分离在一个项目中,另一个是包含测试表格的测试项目。
Solution
├ Test (Test Project)
│ └ Form1
└ WinFormControls (Library Project)
└ ImageButton (UserControl)
该控件附加有TypeConverter
,这是简短的代码。
为了简化问题,我省略了其他方法,您可以从此链接中阅读
public class StateConverter : ExpandableObjectConverter
{
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if(destinationType == typeof(InstanceDescriptor))
{
var ctor = typeof(State).GetConstructor(new Type[] { typeof(int), typeof(Image) });
if (ctor != null)
{
var state = (State)value;
return new InstanceDescriptor(ctor, new object[] { state.GetData(), state.Image });
}
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
错误并不总是发生,这里是重现步骤:
经过一些调试后,我发现此行发生错误:
var state = (State)value;
起初我猜值是空的,所以我添加了一些日志:
try {
var state = (State)value;
} catch (Exception ex) {
File.AppendAllText("errorlog.txt", ex.ToString() +
(value == null ? "NULL" : value.GetType().ToString());
}
最后我得到:
System.InvalidCastException:指定的强制转换无效。 在WinFormControls.ImageButton.StateConverter.ConvertTo处... WinFormControls.ImageButton + State
因此,值不为null,值的类型恰好是我强制转换为的类型。
更新
输出AssemblyQualifiedName IsAssignableFrom为:
value.GetType().AssemblyQualifiedName;
typeof(State).AssemblyQualifiedName;
typeof(State).IsAssignableFrom(value.GetType());
value.GetType().IsAssignableFrom(typeof(State))
value is State
ReferenceEquals(value.GetType(), typeof(State))
结果奇怪:
WinFormControls.ImageButton + State,WinFormControls,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null
WinFormControls.ImageButton + State,WinFormControls,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null
假
假
假
假
两个问题:
这是由于类型转换器和设计器加载类型的方式不同。 当设计人员使用类型解析服务时,类型转换器使用CLR缓存加载类型。 因此,当您更改类库项目并再次构建它时,CLR从CLR中该类型的先前缓存的版本加载程序集,而Designer从新建的程序集加载该程序集,这会导致类型不匹配。
要解决该问题,请在类库项目中:
打开AssemblyInfo.CS
并更改部件版本属性以更改每个内部版本中部件的内部版本号并保存文件。 这将迫使CLR使其缓存无效,并从新版本的程序集中加载新类型:
[assembly: AssemblyVersion("1.0.0.*")]
右键单击并卸载类库项目,然后右键单击并编辑项目文件,然后将项目确定性构建更改为false:
<Deterministic>false</Deterministic>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.