TypeConverter.ConvertTo中的“指定的强制转换无效”错误

问题描述 投票:0回答:1

我正在为我的winform程序进行控制,并且在保存测试表单时会发生此错误。

error


这是解决方案结构,控件库在1个项目中分离,另一个是包含测试表单的测试项目。

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);
    }
}

这里不总是发生错误是重现的步骤:

  1. 打开VS中的solution
  2. 打开Form1设计器,从工具箱中拖动ImageButton
  3. 在ImageButton.cs中进行一些更改(例如添加空格),然后重建解决方案
  4. 返回到Form1设计器,在属性窗口中使用NormalState属性进行一些更改,然后保存,发生错误。
  5. 从那时起,如果你在ImageButton上进行更改并保存,即使从工具箱中拖动另一个ImageButton,错误也会显示,除了重新打开VS.

经过一些调试后,我发现此行发生错误:

var state = (State)value;

起初我猜测值为null,所以我添加了一些日志:

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 假 假 假 假

两个问题:

  1. 为什么会发生错误?
  2. 如何在开发过程中避免它?
c# winforms casting windows-forms-designer typeconverter
1个回答
1
投票

这是因为类型转换器和设计器加载类型的方式不同。类型转换器使用CLR缓存来加载类型,而设计器使用类型解析服务。因此,当您更改类库项目并再次构建它时,CLR从CLR中的类型的先前缓存版本加载程序集,而设计器从新构建的程序集加载它并导致类型不匹配。

要解决这个问题,在类库项目中:

  1. 打开AssemblyInfo.CS并更改程序集版本属性以更改每个构建中程序集的内部版本号并保存文件。这会强制CLR使其缓存无效并从新版本的程序集加载新类型: [assembly: AssemblyVersion("1.0.0.*")]
  1. 右键单击并卸载类库项目,然后右键单击并编辑项目文件,并将项目确定性构建更改为false: <Deterministic>false</Deterministic>

这个问题已经解决了in this forum post

© www.soinside.com 2019 - 2024. All rights reserved.