我有这个奇怪的问题,我无法处理自己。设计为singleton的mvp-project模型中的类会导致InvalidCastException。错误源位于此代码行中,其中反序列化对象被分配给类的实例变量:engineObject = (ENGINE)xSerializer.Deserialize(str);
每当我尝试将一个UserControl添加到表单或不同的UC时,就会出现错误。我所有的UC都有一个特殊的演示者,可以访问上面提到的单例类的实例变量。这是我在尝试在某处添加UC时得到的结果:
'System.TypeInitializationException:'MVP.Model.EngineData'的类型初始值设定项引发了异常。 ----> System.InvalidCastException:[A]引擎无法转换为[B]引擎。类型A源自位于'[...] \ AppData \ Roaming \ Microsoft \ VisualStudio \ 9.0 \ ProjectAssemblies \的上下文'LoadNeither'中的'MVP.Model,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null' uankw1hh01 \ MVP.Model.dll”。类型B源自位于'[...] \ AppData \ Roaming \ Microsoft \ VisualStudio \ 9.0 \ ProjectAssemblies \的上下文'LoadNeither'中的'MVP.Model,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null' u_hge2de01 \ MVP.Model.dll” ...
所以我不知何故有两个程序集,它们不是从我的项目文件夹访问,而是从VS临时文件夹访问?我google了很多,只发现了这个:IronPython Exception: [A]Person cannot be cast to [B]Person。有一个解决方案,但首先它涉及IronPhyton,其次我不知道在我的项目中使用它?
如果你能在这里帮助我,那会很棒:-) THX
答案 0 :(得分:18)
类型是按装配;如果你有两次加载“相同”的程序集,那么程序集的每个“副本”中的类型都不会被认为是同一类型。
当两个程序集位于Load和LoadFrom上下文中时,通常会出现这些问题。见
Difference between LoadFile and LoadFrom with .NET Assemblies?
以及指向suzcook博客的链接,了解有关该问题的详细信息。
另外,请考虑使用融合日志查看器来帮助诊断问题。
http://msdn.microsoft.com/en-us/library/e74a18c4%28VS.71%29.aspx
答案 1 :(得分:4)
根据程序集加载的上下文(上下文为“LoadNeither”)来判断,一些开发人员可能正在做一些事情,比如加载已经内部打包为应用程序资源的程序集。如果这样做,您将使用AppDomain.CurrentDomain.AssemblyResolve事件处理程序,以便您的应用程序可以指定.NET应该获得所需的任何特定程序集的位置。
我的回答不会解释如何做到的诡计 - 但我提到它是因为这个过程直接导致了原始海报遇到的同样的错误。正如Eric Lippert所提到的,类型是按装配。因此,如果您多次加载单个程序集,则相同的已定义类将显示为不同的类 - 即使目视检查显示它们看起来是相同的。
我们已经看到.NET将针对同一DLL多次调用ResolveEventHandler的实例。我不确定为什么.NET有时会这样做(它发生在某些机器上,但不是所有机器上)。但是要解决这个问题,我们需要为加载的程序集保留一个全局句柄列表,这样如果.NET想再次加载程序集,我们会返回最初加载的同一程序集的句柄,而不是将另一个副本加载到内存中
我已经为我们提供了导致问题的代码,并说明了如何正确处理它。
public void AppStartup (object sender, StartupEventArgs e)
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}
public System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
string dllName = args.Name.Contains(',') ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll", "");
dllName = dllName.Replace(".", "_");
if (dllName.EndsWith("_resources")) return null;
System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());
byte[] bytes = null;
try
{
bytes = (byte[])rm.GetObject(dllName);
}
catch (Exception ex)
{
}
if (bytes != null)
{
// the following call will return a newly loaded assembly
// every time it is called
// if this function is called more than once for the same
// assembly, you'll load more than one copy into memory
// this can cause the InvalidCastException
// instead of doing this, you keep a global list of loaded
// assemblies, and return the previously loaded assembly
// handle, instead of loading it again
return System.Reflection.Assembly.Load(bytes);
}
return null;
}
答案 2 :(得分:3)
我的情况涉及同一个dll的两个副本。一个在bin文件夹中,一个在同一bin文件夹的子文件夹中。两者都被加载了,令人惊讶的是有些东西工作得很好,但是有些东西没有,这就是出现这个错误信息的时候:
System.InvalidOperationException; There was an error generating the XML document.; Source: System.Xml; TargetSite: Void Serialize(System.Xml.XmlWriter, System.Object, System.Xml.Serialization.XmlSerializerNamespaces, System.String, System.String);
隐藏在此是以下内部异常(这与Microsoft Dynamics CRM 4.0有关,但可能与任何内容有关)
System.InvalidCastException; [A]XXX.CRMCustomCode.YYY.CreateCompanyRequest cannot be cast to [B]XXX.CRMCustomCode.YYY.CreateCompanyRequest. Type A originates from 'XXX.CRMCustomCode, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'LoadFrom' at location 'C:\Program Files\Microsoft CRM\Server\bin\assembly\XXX.CRMCustomCode.dll'. Type B originates from 'XXX.CRMCustomCode, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'Default' at location 'C:\Program Files\Microsoft CRM\Server\bin\XXX.CRMCustomCode.dll'.;
我只是删除了重复的dll(在C:\ Program Files \ Microsoft CRM \ Server \ bin中),错误就消失了。
答案 3 :(得分:2)
我的特殊情况 - Web应用程序中引用的类库已重命名并重建。较旧版本的库仍在旧名称下的bin文件夹中。框架加载bin文件夹(两个库)中的任何内容并发出此错误。所以它不仅发生在显式加载程序集时。 在我的情况下,明显的解决方案是清理bin文件夹。
答案 4 :(得分:0)
当我尝试更改此演员表时,它可以正常工作:
var t = (TeacherWebPages)Session["TeachersAD"];
对此:
var t = Session["TeachersAD"] as TeacherWebPages;
但是程序集/会话/内存缓存不同,没有数据返回但没有发生错误。因此,以后每次每次源页面从其抱怨的文件夹中更改时,我仍必须删除特定的临时文件,这将需要我从任务管理器中终止IIS进程。或者就我而言,我可以注销并清除会话状态。