由于缺少程序集而导致XmlSerializer.Serialize抛出(但它已经加载)

时间:2015-04-20 14:38:55

标签: c# serialization .net-assembly

我们使用XmlSerializer来序列化来自小类层次结构的对象,如下所示:

Request
|- Request<T>
   |- BarRequest : Request<Bar>
   |- FooRequest : Request<Foo>

Request是一个抽象类,它带有必要的注释,以使XmlSerializer找到子类:

[XmlInclude(typeof(BarRequest))]
[XmlInclude(typeof(FooRequest))]

以这种方式对请求进行序列化和反序列化在一些项目中已经很好地工作了。但是,只要我们在当前项目中为XmlInclude添加FooRequest,我们就会在尝试序列化BarRequest(以及可能任何请求对象)时遇到异常层次结构)。我们甚至还没有序列化任何FooRequest。添加XmlInclude就足够了。

FooRequest可以减少为一个相当不起眼的小班,同时仍然会触发错误:

public class FooRequest: Request<Foo>
{
    protected override Foo Perform()
    {
        throw new NotImplementedException();
    }
}

事实上,它唯一有趣的功能是它引用Foo,它恰好位于程序集FooUI中。我将Foo本身缩减为空公共类而不更改错误。

但是,此时FooUI已成功加载到我的AppDomain中 - 我使用fuslogvw.exe验证了这一点:

*** Protokolleintrag für Assembly-Binder  (20.04.2015 @ 16:14:06) ***

Der Vorgang wurde durchgeführt.
Ergebnis der Bindung: hr = 0x0. Der Vorgang wurde erfolgreich beendet.

Der Assemblymanager wurde geladen aus:  C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll
Als EXE-Datei ausgeführt.  C:\Chem32\CORE\ChemMain.exe
--- Ein detailliertes Fehlerprotokoll folgt. 

=== Zustandsinformationen vor Bindung ===
LOG: Benutzer = <user>
LOG: DisplayName = FooUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
 (Fully-specified)
LOG: Appbase = file:///C:/Chem32/CORE/
LOG: Ursprünglicher PrivatePath = NULL
LOG: DynamicBase = NULL
LOG: CacheBase = NULL
LOG: AppName = NULL
Aufruf von Assembly : FooDriver, Version=5.0.0.1245, Culture=neutral, PublicKeyToken=null.
===
LOG: Diese Bindung startet im LoadFrom-Load-Kontext.
WRN: Das systemeigene Abbild wird nicht im LoadFrom-Kontext durchsucht. Das systemeigene Abbild wird nur im Standard-Load-Kontext durchsucht, z.B. Assembly.Load().
LOG: Die Anwendungskonfigurationsdatei wird verwendet: C:\Chem32\CORE\ChemMain.exe.Config
LOG: Die Computerkonfigurationsdatei von C:\Windows\Microsoft.NET\Framework\v2.0.50727\config\machine.config wird verwendet.
LOG: Die Richtlinie wird derzeit nicht auf den Verweis angewendet (private, benutzerdefinierte, teilweise oder pfadbasierte Assemblybindung)
LOG: Download von neuem URL file:///C:/Chem32/CORE/FooUI.DLL.
LOG: Download von neuem URL file:///C:/Chem32/CORE/FooUI/FooUI.DLL.
LOG: Download von neuem URL file:///C:/Chem32/CORE/Plugins/FooUI.DLL.
LOG: Download von neuem URL file:///C:/Chem32/CORE/Plugins/FooUI/FooUI.DLL.
LOG: Download von neuem URL file:///C:/Chem32/CORE/LCDrivers/FooUI.DLL.
LOG: Download von neuem URL file:///C:/Chem32/CORE/LCDrivers/FooUI/FooUI.DLL.
LOG: Download von neuem URL file:///C:/Chem32/CORE/GCDrivers/FooUI.DLL.
LOG: Download von neuem URL file:///C:/Chem32/CORE/GCDrivers/FooUI/FooUI.DLL.
LOG: Download von neuem URL file:///C:/Chem32/CORE/FooUI.EXE.
LOG: Download von neuem URL file:///C:/Chem32/CORE/FooUI/FooUI.EXE.
LOG: Download von neuem URL file:///C:/Chem32/CORE/Plugins/FooUI.EXE.
LOG: Download von neuem URL file:///C:/Chem32/CORE/Plugins/FooUI/FooUI.EXE.
LOG: Download von neuem URL file:///C:/Chem32/CORE/LCDrivers/FooUI.EXE.
LOG: Download von neuem URL file:///C:/Chem32/CORE/LCDrivers/FooUI/FooUI.EXE.
LOG: Download von neuem URL file:///C:/Chem32/CORE/GCDrivers/FooUI.EXE.
LOG: Download von neuem URL file:///C:/Chem32/CORE/GCDrivers/FooUI/FooUI.EXE.
LOG: Download von neuem URL file:///C:/Chem32/CORE/FooDriver/FooUI.DLL.
LOG: Der Assembly-Download wurde durchgeführt. Datei-Setup wird begonnen: C:\Chem32\CORE\FooDriver\FooUI.dll.
LOG: Die von der Quelle ausgeführte Setup-Phase beginnt.
LOG: Der Assemblyname ist: FooUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
LOG: Codebasis mit where-ref-Bindung stimmt nicht mit dem überein, was im Standardkontext gefunden wurde. Ergebnis im LoadFrom-Kontext behalten.
LOG: Die Bindung war erfolgreich. Assembly wird zurückgegeben von C:\Chem32\CORE\FooDriver\FooUI.dll.
LOG: Die Assembly wird im LoadFrom-Load-Kontext geladen.

此时,我应该注意各个有趣位的位置:

C:\Chem32\CORE\ChemMain.exe - Main executable
C:\Chem32\CORE\FooDriver\FooDriver.dll - Plugin loaded by ChemMain.exe
C:\Chem32\CORE\FooDriver\FooUI.dll - Assembly containing class Foo

如上所示,程序集在FooDriver子文件夹中找到并正确加载。但是,一旦程序尝试序列化BarRequest,我就会得到以下异常:

System.InvalidOperationException: Beim Generieren des XML-Dokuments ist ein Fehler aufgetreten. ---> System.IO.FileNotFoundException: Die Datei oder Assembly "FooUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" oder eine Abhängigkeit davon wurde nicht gefunden. Das System kann die angegebene Datei nicht finden.
Dateiname: "FooUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
   bei Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterRequest.Write27_Request(String n, String ns, Request o, Boolean isNullable, Boolean needType)
   bei Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterRequest.Write28_Request(Object o)

=== Zustandsinformationen vor Bindung ===
LOG: Benutzer = <user>
LOG: DisplayName = FooUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
 (Fully-specified)
LOG: Appbase = file:///C:/Chem32/CORE/
LOG: Ursprünglicher PrivatePath = NULL
Aufruf von Assembly : (Unknown).
===
LOG: Diese Bindung startet im default-Load-Kontext.
LOG: Die Anwendungskonfigurationsdatei wird verwendet: C:\Chem32\CORE\ChemMain.exe.Config
LOG: Die Computerkonfigurationsdatei von C:\Windows\Microsoft.NET\Framework\v2.0.50727\config\machine.config wird verwendet.
LOG: Die Richtlinie wird derzeit nicht auf den Verweis angewendet (private, benutzerdefinierte, teilweise oder pfadbasierte Assemblybindung)
LOG: Download von neuem URL file:///C:/Chem32/CORE/FooUI.DLL.
LOG: Download von neuem URL file:///C:/Chem32/CORE/FooUI/FooUI.DLL.
LOG: Download von neuem URL file:///C:/Chem32/CORE/Plugins/FooUI.DLL.
LOG: Download von neuem URL file:///C:/Chem32/CORE/Plugins/FooUI/FooUI.DLL.
LOG: Download von neuem URL file:///C:/Chem32/CORE/LCDrivers/FooUI.DLL.
LOG: Download von neuem URL file:///C:/Chem32/CORE/LCDrivers/FooUI/FooUI.DLL.
LOG: Download von neuem URL file:///C:/Chem32/CORE/GCDrivers/FooUI.DLL.
LOG: Download von neuem URL file:///C:/Chem32/CORE/GCDrivers/FooUI/FooUI.DLL.
LOG: Download von neuem URL file:///C:/Chem32/CORE/FooUI.EXE.
LOG: Download von neuem URL file:///C:/Chem32/CORE/FooUI/FooUI.EXE.
LOG: Download von neuem URL file:///C:/Chem32/CORE/Plugins/FooUI.EXE.
LOG: Download von neuem URL file:///C:/Chem32/CORE/Plugins/FooUI/FooUI.EXE.
LOG: Download von neuem URL file:///C:/Chem32/CORE/LCDrivers/FooUI.EXE.
LOG: Download von neuem URL file:///C:/Chem32/CORE/LCDrivers/FooUI/FooUI.EXE.
LOG: Download von neuem URL file:///C:/Chem32/CORE/GCDrivers/FooUI.EXE.
LOG: Download von neuem URL file:///C:/Chem32/CORE/GCDrivers/FooUI/FooUI.EXE.

   --- Ende der internen Ausnahmestapelüberwachung ---

Server stack trace: 
   bei System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
   bei System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o)

InvalidOperationException的异常文本等同于&#34;生成XML文档时出错。&#34;和FileNotFoundException说&#34;无法加载文件要么 装配&#39; X&#39;或其中一个依赖项。&#34;

如您所见,它尝试加载已加载的相同程序集,但不会尝试查看FooDriver子目录。同样有趣的是,它将调用程序集显示为&#34;(未知)&#34;。

现在这里有一个非常有趣且令人困惑的地方:如果我将Foo移动到位于同一文件夹中的不同外部程序集中,事情就会突然发生。我不知道是什么让这个其他装配不同。

我们赞赏任何有关新方向的指示。

1 个答案:

答案 0 :(得分:1)

你是如何加载你的插件的? .Net中有各种加载上下文。见这里:https://msdn.microsoft.com/en-us/library/dd153782%28v=vs.110%29.aspx

可以将程序集加载到不同的上下文中,这会导致此类绑定解析问题。听起来你可能在你的插件目录中做了一个LoadFile。使用Assembly.LoadFrom并获取AssemblyName应该可以解决问题。