在 C# 中序列化和反序列化外部程序集

发布于 2024-09-02 22:11:15 字数 111 浏览 6 评论 0原文

我编写了一个插件系统,我想保存/加载它们的属性,以便在程序重新启动时它们可以继续工作。我使用二进制序列化。问题是它们可以序列化但不能反序列化。 在反序列化期间,抛出“无法找到程序集”异常。如何恢复序列化数据?

I wrote a plugin system and I want to save/load their properties so that if the program is restarted they can continue working. I use binary serialization. The problem is they can be serialized but not deserialized.
During the deserialization "Unable to find assembly" exception is thrown. How can I restore serialized data?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

薄荷港 2024-09-09 22:11:15

好吧,我在这里找到了一些东西。 :)

http://techdigger .wordpress.com/2007/12/22/deserializing-data-into-a-dynamically-loaded- assembly/

我使用了这种方法,并且它的工作没有任何问题。

首先定义了一个活页夹类:

    internal sealed class VersionConfigToNamespaceAssemblyObjectBinder : SerializationBinder {

      public override Type BindToType(string assemblyName, string typeName) {

       Type typeToDeserialize = null;

       try{

         string ToAssemblyName = assemblyName.Split(',')[0];

         Assembly[] Assemblies = AppDomain.CurrentDomain.GetAssemblies();

         foreach (Assembly ass in Assemblies){

           if (ass.FullName.Split(',')[0] == ToAssemblyName){

               typeToDeserialize = ass.GetType(typeName);

               break;

           }

         }

       }

       catch (System.Exception exception){

         throw exception;

       }

       return typeToDeserialize;

      }

    }

然后是序列化方法:

            public static byte[] Serialize(Object o){           

             MemoryStream stream = new MemoryStream();

             BinaryFormatter formatter = new BinaryFormatter();

             formatter.AssemblyFormat

                 = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;

             formatter.Serialize(stream, o);

             return stream.ToArray();

            }


            public static Object BinaryDeSerialize(byte[] bytes){

              MemoryStream stream = new MemoryStream(bytes);

              BinaryFormatter formatter = new BinaryFormatter();

              formatter.AssemblyFormat 

                  = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;

              formatter.Binder 

                  = new VersionConfigToNamespaceAssemblyObjectBinder();

              Object obj = (Object)formatter.Deserialize(stream);

              return obj;

            }

我在需要的地方使用它们。

            protected void SaveAsBinary(object objGraph, string fileName)

            {

              byte[] serializedData = Serialize(objGraph);

              File.WriteAllBytes(fileName, serializedData);

            }


            protected object LoadFomBinary(string fileName)

            {     

              object objGraph = null;

              try

              {

                objGraph = BinaryDeserialize(File.ReadAllBytes(fileName));

              }

              catch (FileNotFoundException fne)

              {

            #if DEBUG

                throw fne;

            #endif

              }      

              return objGraph;

            }

感谢您的帮助:)

Ok here I have found something. :)

http://techdigger.wordpress.com/2007/12/22/deserializing-data-into-a-dynamically-loaded-assembly/

I used this approach and it worked without any problem.

Firs defined a binder class:

    internal sealed class VersionConfigToNamespaceAssemblyObjectBinder : SerializationBinder {

      public override Type BindToType(string assemblyName, string typeName) {

       Type typeToDeserialize = null;

       try{

         string ToAssemblyName = assemblyName.Split(',')[0];

         Assembly[] Assemblies = AppDomain.CurrentDomain.GetAssemblies();

         foreach (Assembly ass in Assemblies){

           if (ass.FullName.Split(',')[0] == ToAssemblyName){

               typeToDeserialize = ass.GetType(typeName);

               break;

           }

         }

       }

       catch (System.Exception exception){

         throw exception;

       }

       return typeToDeserialize;

      }

    }

And then serialization methods:

            public static byte[] Serialize(Object o){           

             MemoryStream stream = new MemoryStream();

             BinaryFormatter formatter = new BinaryFormatter();

             formatter.AssemblyFormat

                 = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;

             formatter.Serialize(stream, o);

             return stream.ToArray();

            }


            public static Object BinaryDeSerialize(byte[] bytes){

              MemoryStream stream = new MemoryStream(bytes);

              BinaryFormatter formatter = new BinaryFormatter();

              formatter.AssemblyFormat 

                  = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;

              formatter.Binder 

                  = new VersionConfigToNamespaceAssemblyObjectBinder();

              Object obj = (Object)formatter.Deserialize(stream);

              return obj;

            }

And I use them where I need.

            protected void SaveAsBinary(object objGraph, string fileName)

            {

              byte[] serializedData = Serialize(objGraph);

              File.WriteAllBytes(fileName, serializedData);

            }


            protected object LoadFomBinary(string fileName)

            {     

              object objGraph = null;

              try

              {

                objGraph = BinaryDeserialize(File.ReadAllBytes(fileName));

              }

              catch (FileNotFoundException fne)

              {

            #if DEBUG

                throw fne;

            #endif

              }      

              return objGraph;

            }

Thanks for help :)

白龙吟 2024-09-09 22:11:15

使用fuslogvw.exe工具找出CLR在哪里搜索程序集。

Use the fuslogvw.exe tool to find out where the CLR is searching for the assembly.

吃素的狼 2024-09-09 22:11:15

很可能,您的插件程序集在您反序列化数据时尚未加载。因为它是一个外部插件程序集,所以我猜您正在显式加载它。您可能在加载程序集之前反序列化属性对象。您可以通过挂钩当前 AppDomain 上的 AssemblyResolve 和 AssemblyLoad 事件并准确观察它们的调用时间来诊断和修复问题。

您还可以使用 AssemblyResolve 自行将显式程序集加载代码放入其中并返回加载的程序集来修复加载错误。我不推荐这个,因为它有点倒退。

AssemblyResolve

More than likely, your plugin assembly is not loaded at the time that you're deserializing the data. Because it's an external, plugin assembly, I'm guessing you're explicitly loading it. You are probably deserializing the properties object before loading the assembly. You can diagnose and fix the problem by hooking the AssemblyResolve and AssemblyLoad events on the current AppDomain and observing exactly when they're called.

You can also use AssemblyResolve to fix the load error by putting explicit Assembly load code in it yourself and returning the loaded assembly. I don't recommend this because it's kindof backwards.

AssemblyResolve

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文