【发布时间】:2019-03-10 05:12:10
【问题描述】:
我正在为我的 winform 程序制作控件,保存测试表单时出现此错误。
这是解决方案结构,控件库分为一个项目,另一个是包含测试表单的测试项目。
Solution
├ Test (Test Project)
│ └ Form1
└ WinFormControls (Library Project)
└ ImageButton (UserControl)
控件附有TypeConverter,这里是简要代码。
为了问题简单,我省略了其他方法,大家可以阅读this link
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);
}
}
错误并不总是发生在这里是重现的步骤:
- 在VS中打开solution
- 打开 Form1 设计器,从工具箱中拖出一个 ImageButton
- 在 ImageButton.cs 中进行一些更改(例如,添加一个空格),然后重新生成解决方案
- 返回Form1设计器,在属性窗口中修改NormalState属性,然后保存,出现错误。
- 从那时起,如果您在 ImageButton 上进行更改并保存,即使从工具箱中拖动另一个 ImageButton,也会显示错误,除非重新打开 VS。
经过一些调试,我发现错误发生在这一行:
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
所以值不为空,值的类型正是我所转换的。
更新
输出 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,版本=1.0.0.0,文化=中性,PublicKeyToken=null
假的
假的
假的
假的
两个问题:
- 为什么会发生错误?
- 在开发过程中如何避免它?
【问题讨论】:
-
看起来确实很奇怪...你确定 (value == null || typeof(State) == value.GetType()) 吗?
-
这很痛苦,但我想你需要关闭VS并清除设计器程序集缓存。看看this post。您需要考虑的另一件事是在
ConvertTo中检查if (value is State),但这不能解决问题,但通常在类型转换器中需要。 -
@EricMcLachlan 看到捕获代码,我确定值不为空(状态是一个结构,所以理论上它也不会为空)并且我的问题的更新,我尝试输出两种类型的
AssemblyQualifiedName,它们是相同的。 -
@EricMcLachlan 设计器中类和结构之间的行为几乎不同,很难改变,但可以选择。
typeof(value.GetType()).IsAssignableFrom(State)也是假的,好像这两种完全不一样,可能是缓存问题。 -
感谢@RezaAghaei 检查
is State很有帮助。
标签: c# winforms casting windows-forms-designer typeconverter