使用IXmlSerializable发出引用外部库的System.Xml

时间:2013-11-11 21:32:11

标签: c# serialization xamarin.ios xamarin

我已更新到最新版本的Xamarin Studio,并且我使用与Visual Studio共享的类不再在两个平台之间工作。我遇到了一些涉及XML序列化的编译/运行时错误。我有一个库,其中包含在Xamarin工作室中编译的以下类:

[XmlRoot("dictionary")]
[Serializable]
public class SerializableDictionary<TKey, TValue>
    : Dictionary<TKey, TValue>, IXmlSerializable
{
    #region IXmlSerializable Members

    public SerializableDictionary()
    {

    }

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

        bool wasEmpty = reader.IsEmptyElement;
        reader.Read();

        if (wasEmpty)
            return;

        while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
        {
            reader.ReadStartElement("item");

            reader.ReadStartElement("key");
            TKey key = (TKey)keySerializer.Deserialize(reader);
            reader.ReadEndElement();

            reader.ReadStartElement("value");
            TValue value = (TValue)valueSerializer.Deserialize(reader);
            reader.ReadEndElement();

            this.Add(key, value);

            reader.ReadEndElement();
            reader.MoveToContent();
        }
        reader.ReadEndElement();
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

        foreach (TKey key in this.Keys)
        {
            writer.WriteStartElement("item");

            writer.WriteStartElement("key");
            keySerializer.Serialize(writer, key);
            writer.WriteEndElement();

            writer.WriteStartElement("value");
            TValue value = this[key];
            valueSerializer.Serialize(writer, value);
            writer.WriteEndElement();

            writer.WriteEndElement();
        }
    }
    #endregion
}

我编译了这个DLL,并在Visual Studio的Windows项目中引用它,如下所示:

SerializableDictionary<string, string> asdf = new SerializableDictionary<string, string>();

这给出了编译错误: “类型'System.Xml.Serialization.IXmlSerializable'是在未引用的程序集中定义的。您必须添加对程序集'System.Xml,Version = 2.0.5.0,Culture = neutral,PublicKeyToken = 7cec85d7bea7798e'”<的引用/ p>

当然,我实际上有一个System.Xml的引用。事实上,如果我从Xamarin复制该类并将其粘贴到Visual Studio端的项目中,该类工作正常。根据我如何构建事物,这个错误有一些变化,但这个似乎是根本原因。

任何人都知道为什么这个库不再跨平台工作?在最新版本的Xamarin中,IXmlSerializable发生了什么变化?

4 个答案:

答案 0 :(得分:1)

如果你想在Visual Studio中的Xamarin.iOS和你的项目之间共享程序集,你必须确保它们构建在相同的核心库之上(mscorlib,...)

我猜您的Xamarin.iOS项目是基于2.0.5.0个人资料,而您的其他项目是4.0.0.0

该主题也在forum

上讨论

答案 1 :(得分:1)

  

当然,我实际上有一个对System.Xml的引用。

我遇到了一个类似的问题,我错误地认为有一个using System.Xml语句没有错误(足够)是一个包含所需类型的引用...特别是因为我没有编译时错误。

using System.Xml

显然,即使它允许using System.Xml(打包在默认的System.Xml库中),它也不包含所需的System.Xml.Serialization.IXmlSerializable

初始System引用:

Current System References

所以解决方案是明确添加对Framework程序集的引用; System.Xml

Explicit reference to System.Xml Assembly

答案 2 :(得分:0)

System.XML命名空间既存在于System.XML程序集中,也存在于System.Data中(这是导致混淆的原因)

Teemu准确地解释了这一点:https://bytes.com/topic/asp-net/answers/645579-you-must-add-reference-assembly-system-xml

帖子如下: 您好,

使用System.Xml;

意味着您已经引用了System.Xml.dll程序集。它的意思是 您只是导入该命名空间,尝试快速键入需要 驻留在System.Xml名称空间中的完全限定类型的名称。

命名空间是逻辑概念,并不一定总是有用 与集会在一起。例如:System.Configuration命名空间跨度 两个程序集:System.dll和System.Configuration.dll

因此,尝试使用添加引用对话框在VS中获取引用(/右键单击

解决方案资源管理器中的

项目)

Teemu Keiski AspInsider,ASP.NET MVP

答案 3 :(得分:0)

从我的角度来看,Stephane Delcroix正确地回答了这个问题,但是你可以采取以下措施:

注意如果您可以控制外部库您不应该使用此方法您应该为Xamarin目标编译它们或使用.net标准库/ PCL。

仅使用此方法作为最后的手段!

但是如果您不能控制外部库并仍然需要在Xamarin应用程序中使用它们,那么您可以执行以下操作:

请注意,这些说明适用于Android,但相同的方法可能适用于iOS。

修改Xamarin System.Xml.dll文件,使其与所需的System.Xml.dll版本相同。

  • C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v1.0\System.Xml复制到可写位置。 (我们将此称为E:\

  • 反汇编System.Xml.dll:

    E:&gt;“c:\ Program Files(x86)\ Microsoft SDKs \ Windows_v7.0A \ Bin \ ildasm.exe”System.Xml.dll /out=e:/System.Xml.asm"

  • 修改asm

您可以使用此补丁(作为指南):

--- E:\System.Xml.orig.asm
+++ E:\System.Xml.asm
@@ -127,19 +127,10 @@
   .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
                                                                                                              63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
   .permissionset reqmin
-             = {class 'System.Security.Permissions.SecurityPermissionAttribute, mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' = {property bool 'SkipVerification' = bool(true)}}
-  .publickey = (00 24 00 00 04 80 00 00 94 00 00 00 06 02 00 00   // .$..............
-                00 24 00 00 52 53 41 31 00 04 00 00 01 00 01 00   // .$..RSA1........
-                8D 56 C7 6F 9E 86 49 38 30 49 F3 83 C4 4B E0 EC   // .V.o..I80I...K..
-                20 41 81 82 2A 6C 31 CF 5E B7 EF 48 69 44 D0 32   //  A..*l1.^..HiD.2
-                18 8E A1 D3 92 07 63 71 2C CB 12 D7 5F B7 7E 98   // ......cq,..._.~.
-                11 14 9E 61 48 E5 D3 2F BA AB 37 61 1C 18 78 DD   // ...aH../..7a..x.
-                C1 9E 20 EF 13 5D 0C B2 CF F2 BF EC 3D 11 58 10   // .. ..]......=.X.
-                C3 D9 06 96 38 FE 4B E2 15 DB F7 95 86 19 20 E5   // ....8.K....... .
-                AB 6F 7D B2 E2 CE EF 13 6A C2 3D 5D D2 BF 03 17   // .o}.....j.=]....
-                00 AE C2 32 F6 C6 B1 C7 85 B4 30 5C 12 3B 37 AB ) // ...2......0\.;7.
+             = {class 'System.Security.Permissions.SecurityPermissionAttribute, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' = {property bool 'SkipVerification' = bool(true)}}
+  .publickey = (00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 ) 
   .hash algorithm 0x00008004
-  .ver 2:0:5:0
+  .ver 4:0:0:0
 }
 .module System.Xml.dll
 // MVID: {4AB28EE6-F5EC-49E1-A1A7-69D0920BF2EC}
@@ -149,7 +140,7 @@
 .stackreserve 0x00100000
 .subsystem 0x0003       // WINDOWS_CUI
 .corflags 0x00000001    //  ILONLY
-// Image base: 0x05580000
+// Image base: 0x05300000


 // =============== CLASS MEMBERS DECLARATION ===================
@@ -201,7 +192,7 @@
   .field public static literal string FxFileVersion = "4.0.50524.0"
   .field public static literal string EnvironmentVersion = "4.0.50524.0"
   .field public static literal string VsFileVersion = "9.0.50727.42"
-  .field private static literal string PublicKeyToken = "7cec85d7bea7798e"
+  .field private static literal string PublicKeyToken = "b77a5c561934e089"
   .field public static literal string AssemblyI18N = "I18N, Version=2.0.5.0, Culture=neutral, PublicKeyT"
   + "oken=0738eb9f132ed756"
   .field public static literal string AssemblyMicrosoft_JScript = "Microsoft.JScript, Version=2.0.5.0, Culture=neutra"
@@ -619213,4 +619204,4 @@
 .data D_00273E18 = bytearray (
                  20 00 09 00 0A 00 0D 00)                         //  .......
 // *********** DISASSEMBLY COMPLETE ***********************
-// WARNING: Created Win32 resource file e:/System.Xml.orig.res+// WARNING: Created Win32 resource file e:/System.Xml.res

这会将2.0.5.0版本号更改为4.0.0.0并更新公钥令牌。 (从7cec85d7bea7798e到b77a5c561934e089)

  • 重新组装

    E:&gt; c:\ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ ilasm.exe / dll /output=System.Xml.dll System.Xml.asm /Resource=System.Xml.res

首先备份原始System.Xml.dll。

  • 将'fixed'System.Xml复制回C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v1.0\

再次仅使用此方法作为最后的手段!