我的所有.NET序列化程序集被错误地标识为错误版本,并被丢弃。
我已经在GitHub上为此问题创建了一个示例项目 https://github.com/stewienj/StewienCodeExamples/tree/master/SerializationFail
我使用下面的目标预先生成了一个序列化程序集,但是即使该程序集已由XmlSerializer加载,也会由于过期而被丢弃。我假设使用免费版本的JetBrains DotPeek作为Symbol Server遍历system.xml.dll代码时所发现的内容,以此为前提。这是我的自定义构建目标:
<Target
Name="GeneratePregeneratedSerializersSigned"
Beforetargets="AfterBuild"
DependsOnTargets="AssignTargetPaths;Compile;ResolveKeySource"
Inputs="$(MSBuildAllProjects);@(IntermediateAssembly)"
Outputs="$(OutputPath)$(_SGenDllName)"
Condition="Exists('PregeneratedSerializers.cs')
>
<PropertyGroup>
<SGenToolPath Condition="'$(Platform)'=='x64'">$(SDK40ToolsPath)x64\</SGenToolPath>
<SGenToolPath Condition="'$(Platform)'!='x64'">$(SDK40ToolsPath)</SGenToolPath>
<SGenKeyFile Condition="'$(SignAssembly)'=='true'">SerializationFail.snk</SGenKeyFile>
<SGenKeyFile Condition="'$(SignAssembly)'!='true'">
</SGenKeyFile>
</PropertyGroup>
<SGen
BuildAssemblyName="$(TargetFileName)"
BuildAssemblyPath="$(OutputPath)"
References="@(ReferencePath)"
ShouldGenerateSerializer="true"
UseProxyTypes="false"
KeyFile="$(SGenKeyFile)"
ToolPath="$(SGenToolPath)"
Platform="$(PlatformTarget)"
Types="$(RootNamespace).PregeneratedSerializers"
>
<Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly" />
</SGen>
<Message Importance="High" Text="$(MSBuildProjectName) -> $(OutputPath)$(_SGenDllName)" />
</Target>
在此处找到将DotPeek用作符号服务器的说明 https://www.jetbrains.com/help/decompiler/2016.1/Using_product_as_a_Symbol_Server.html
如果我进入XmlSerializer,最终会遇到system.xml.Serialization.TempAssembly类中名为IsSerializerVersionmatch的方法,它看起来像这样:
private static bool IsSerializerVersionmatch(Assembly serializer,Type type,string defaultNamespace,string location)
{
if (serializer == (Assembly) null)
return false;
object[] customAttributes = serializer.getcustomAttributes(typeof (XmlSerializerVersionAttribute),false);
if (customAttributes.Length != 1)
return false;
XmlSerializerVersionAttribute versionAttribute = (XmlSerializerVersionAttribute) customAttributes[0];
return versionAttribute.ParentAssemblyId == TempAssembly.GenerateAssemblyId(type) && versionAttribute.Namespace == defaultNamespace;
}
由于某种原因,这似乎返回了false,因为我最终在调试器中出现了
这会产生后续影响,临时Seralizer生成器失败,因为它无法使用我在XmlColor上具有的隐式转换器,这是另一个问题(编辑:此问题在.NET 4.8中已修复)。编写器创建成功,只是失败的读取器,因为它找不到从XmlColor到Color的隐式转换器。
另一个问题是,当我尝试迭代内存中的所有类型时,应用程序崩溃,这似乎与生成的类型有关。
我认为我做错了什么,否则我的电脑正在做某事,导致生成的XmlSerializer失败,或者.NET框架中存在一个从逐步查看源代码不明显的错误(我我使用的是.NET版本4.7.2,也出现在4.8中)。只有第一种选择似乎是合理的,那么我在做什么错了?
该示例应用程序显示源程序集ID等于序列化程序集中嵌入的父程序集ID,并且名称空间为null。类型列表显示正在生成用于序列化的代码,而不是使用预生成的序列化器(单击绿色按钮后便可见)。我不知道为什么会这样,单步执行代码并查看变量还会显示通过IsSerializerVersionmatch测试通过的所有条件。