简体   繁体   English

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

[英]“Specified cast is not valid” error in TypeConverter.ConvertTo

I'm making controls for my winform program, and this error happens when saving the test form. 我正在为Winform程序进行控制,并且在保存测试表单时会发生此错误。

错误


This is the solution structure, the controls library is seperated in 1 project and another is a test project contains a test form. 这是解决方案结构,控件库分离在一个项目中,另一个是包含测试表格的测试项目。

Solution
├ Test (Test Project)
│ └ Form1
└ WinFormControls (Library Project)
  └ ImageButton (UserControl)

The control has a TypeConverter attached, here is brief code. 该控件附加有TypeConverter ,这是简短的代码。

To make the question simple, I omit other methods, you can read it from 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);
    }
}

The error is not always happens here are steps to reproduce: 错误并不总是发生,这里是重现步骤:

  1. Open the solution in VS 在VS中打开解决方案
  2. Open the Form1 designer, drag an ImageButton from toolbox 打开Form1设计器,从工具箱中拖动一个ImageButton
  3. Make some change in ImageButton.cs (eg. add a space), then rebuild the solution 在ImageButton.cs中进行一些更改(例如,添加一个空格),然后重新构建解决方案
  4. Return to the Form1 designer, make some change with NormalState property in the properties window, then save, the error occurs. 返回到Form1设计器,在属性窗口中使用NormalState属性进行一些更改,然后保存,则发生错误。
  5. Since then if you make change on the ImageButton and save, the error will show, even if drag another ImageButton from the toolbox, except reopen the VS. 从那时起,如果您对ImageButton进行更改并保存,则即使重新打开VS,即使从工具箱中拖动另一个ImageButton,也会显示错误。

After some debug, I found the error occurs with this line: 经过一些调试后,我发现此行发生错误:

var state = (State)value;

At first I guessed the value is null, so I added some log with it: 起初我猜值是空的,所以我添加了一些日志:

try {
    var state = (State)value;
} catch (Exception ex) {
    File.AppendAllText("errorlog.txt", ex.ToString() +
       (value == null ? "NULL" : value.GetType().ToString());
}

Finally I got: 最后我得到:

System.InvalidCastException: Specified cast is not valid. System.InvalidCastException:指定的强制转换无效。 at WinFormControls.ImageButton.StateConverter.ConvertTo ...... WinFormControls.ImageButton+State 在WinFormControls.ImageButton.StateConverter.ConvertTo处... WinFormControls.ImageButton + State

So the value is not null, and the type of value is exactly what I cast to. 因此,值不为null,值的类型恰好是我强制转换为的类型。


Update 更新

Output AssemblyQualifiedName, IsAssignableFrom, is: 输出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))

Strange result: 结果奇怪:

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

Two questions: 两个问题:

  1. Why the error happens? 为什么会发生错误?
  2. How can I avoid it during developing? 在开发过程中如何避免这种情况?

This is because of the different way that type converter and designer loads the type. 这是由于类型转换器和设计器加载类型的方式不同。 Type converter uses CLR cache to load the type while designer uses type resolutions service. 当设计人员使用类型解析服务时,类型转换器使用CLR缓存加载类型。 So when you change the class library project and build it again, the CLR loads the assembly from previously cached version of the type in CLR, while designer loads it from newly built assembly and it results in a type mismatch. 因此,当您更改类库项目并再次构建它时,CLR从CLR中该类型的先前缓存的版本加载程序集,而Designer从新建的程序集加载该程序集,这会导致类型不匹配。

To solve the problem, in the class library project: 要解决该问题,请在类库项目中:

  1. Open AssemblyInfo.CS and change assembly version attribute to change the build number of the assembly in each build and save the file. 打开AssemblyInfo.CS并更改部件版本属性以更改每个内部版本中部件的内部版本号并保存文件。 This forces the CLR to invalidate its cache and load the new type from the new version of assembly: 这将迫使CLR使其缓存无效,并从新版本的程序集中加载新类型:

    [assembly: AssemblyVersion("1.0.0.*")]

  1. Right click and unload the class library project, then right click and edit the project file and change the project deterministic build to false: 右键单击并卸载类库项目,然后右键单击并编辑项目文件,然后将项目确定性构建更改为false:

    <Deterministic>false</Deterministic>

The problem is already addressed in this forum post . 这个论坛帖子已经解决了这个问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM