当从父应用程序动态加载的程序集调用时,XMLSerializer 无法保存/加载?

发布于 2024-09-07 12:22:13 字数 1741 浏览 0 评论 0原文

我正在为应用程序编写一个插件 dll。应用程序通过以下方式加载插件程序集:

assembly = Assembly.Load(System.IO.File.ReadAllBytes(filename)); 

当我尝试序列化/反序列化公共类时,问题就会显现出来。我将其范围缩小到序列化:

public BindingList<MyClass> MyClasses
    { get; set; }

如果我将其注释掉,就没有问题。如果我尝试序列化:

        public static void SaveSettingsFile()
        {
            try
            {
                XmlSerializer ser = new XmlSerializer(typeof(GameTimeSettings));

                TextWriter writer = new StreamWriter(SettingPath);
                ser.Serialize(writer, Settings.Instance);
                writer.Close();
            }
            catch (Exception e)
            {
                Logger.ReportException("SaveSettingsFile", e);
                Logger.ReportException("SaveSettingsFile->InnerException", e.InnerException);
            }
        }

ser.Serialize(writer, Settings.Instance) 抛出异常:

System.InvalidOperationException Msg=There is an error in XML document (0,, 0). ->
InnerException: Object reference not set to an instance of an object.

我的类有一个默认的空构造函数。我尝试过使用 sgen。在我编写的一个简单的测试台应用程序中,序列化工作正常......只有当程序集动态加载时才会出错。

此外,从这两个线程中,

http://forums.gbpvr .com/showthread.php?30384-XMLSerializer-Problems-with-Plugins , http://forums.gbpvr.com/showthread.php?32197-System.XML-Deserialization

我知道我可以将类型从 BindingList 更改为 ArrayList 并使其工作;但是,我想继续数据绑定工作,因为有很多设置需要管理。

任何意见将不胜感激。

I am writing a plugin dll for an application. The application loads plugin assemblies via:

assembly = Assembly.Load(System.IO.File.ReadAllBytes(filename)); 

The problem manifests itself when I attempt to serialize/deserialize a plublic class. I narrowed it down to the serialization of:

public BindingList<MyClass> MyClasses
    { get; set; }

If I comment this out, no problems. If I attempt to serialize with:

        public static void SaveSettingsFile()
        {
            try
            {
                XmlSerializer ser = new XmlSerializer(typeof(GameTimeSettings));

                TextWriter writer = new StreamWriter(SettingPath);
                ser.Serialize(writer, Settings.Instance);
                writer.Close();
            }
            catch (Exception e)
            {
                Logger.ReportException("SaveSettingsFile", e);
                Logger.ReportException("SaveSettingsFile->InnerException", e.InnerException);
            }
        }

An exception is thrown on ser.Serialize(writer, Settings.Instance) :

System.InvalidOperationException Msg=There is an error in XML document (0,, 0). ->
InnerException: Object reference not set to an instance of an object.

My class has a default, empty constructor. I have tried using sgen. In a simple testbed application I wrote, serialization works fine... it's only when the Assembly is dynamically loaded does it fault.

Furthermore, from these two threads,

http://forums.gbpvr.com/showthread.php?30384-XMLSerializer-Problems-with-Plugins , http://forums.gbpvr.com/showthread.php?32197-System.XML-Deserialization

I know I can change the type from BindingList to ArrayList and have it work; however, I would like to keep databinding working as there are quite a bit of settings to manage.

Any input would be appreciated.

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

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

发布评论

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

评论(2

迟到的我 2024-09-14 12:22:13

到目前为止,John Saunders 的评论似乎是正确的,您可能没有初始化 MyClasses

既然你说它与 SGen 配合得很好,你可能还想检查它是否与编译标志有关,比如尝试将其设置为发布,看看是否会改变事情。

John Saunders' comment appears correct for this so far, you likely are not initializing MyClasses.

Since you say it works fine with SGen, you might also want to check if it has something to do with the compile flags, like maybe try setting it to release and see if that changes things.

长安忆 2024-09-14 12:22:13

很抱歉把这个从坟墓里拉出来,但我今天再次遇到了类似的问题,这是第一个谷歌结果,所以我想我会分享。

这似乎是我不久前尝试编写 MSBuild 自定义任务(基本上是一个插件)时遇到的问题的一般情况。我在 MSDN 上发布了有关它的信息论坛

这是评论中最相关的部分,只需将 MSBuild 替换为任何具有插件架构的应用程序,并将 CruiseControl.NET 库替换为任何使用 XmlSerializer 的库:

所讨论的库是 ThoughtWork 的 CruiseControl.NET 的远程处理库,该库使用 .NET 远程处理和一些客户端激活的对象。当您尝试激活该对象时,.NET 的二进制序列化器将开始尝试找出从何处加载 ThoughtWorks.CruiseControl 程序集,以便它可以读取该对象(我们在 1.4.4SP1 中使用 ThoughtWorks.CruiseControl.Remote.dll)正在使用)问题是二进制序列化器的 GetAssembly 逻辑没有意识到 MSBuild 已经执行了一些巫术来从任意位置加载自定义程序集。

因此,它默认尝试按照 http://msdn.microsoft.com/en-us/library/yx7xezcf%28v=VS.100%29.aspx 这意味着如果没有找到它在 GAC 中将从程序启动的位置开始探测,并且由于 MSBuild 是从 %FrameworkDir%/%FrameworkVersion% 文件夹启动的,因此不太可能找到它正在寻找的程序集。

这解释了为什么您不会在控制台应用程序中看到此问题(程序集很可能位于控制台应用程序旁边)

MSDN 论坛帖子中提供的解决方案也适用于此处,基本上他们添加了一个额外的事件处理程序来尝试从已知位置进行探测,我再次引用了相关部分:

对于任何关心的人,解决方法是为 AppDomain.AssemblyResolve 事件注册一个处理程序,并注册到那里的 Assembly.LoadFrom()。

就我个人而言,这让我感到害怕,但这是我发现的唯一有效的解决方案,更多的谷歌搜索并没有向我显示 Microsoft Connect 问题,但它很可能不会被修复或者是设计使然。

Sorry to pull this up from the grave, but I ran into a similar issue again today and this was the first google result, so I thought I'd share.

This appears to be a generic case of an issue I had ran into awhile back when attempting to write an MSBuild Custom task (basically a plugin). I posted about it on the MSDN Forums.

Here is the most relevant part of the comment, simply substitute MSBuild for any application that has a plugin architecture, and the CruiseControl.NET library for any library that uses the XmlSerializer:

The Library in question is the Remoting Library for ThoughtWork's CruiseControl.NET, this library uses .NET Remoting with some Client Activated Objects. When you go to attempt to activate the object, .NET's Binary Serializer goes to work trying to figure out where to load the ThoughtWorks.CruiseControl assembly from so it can read the object (ThoughtWorks.CruiseControl.Remote.dll in 1.4.4SP1 which we're using) the problem is the Binary Serializer's GetAssembly Logic doesn't realize that MSBuild has performed some voodoo to load the custom assembly from an arbitrary location.

Therefore it defaults to attempting to look in the same directory that the program is located in as per http://msdn.microsoft.com/en-us/library/yx7xezcf%28v=VS.100%29.aspx which means if it didn't find it in the GAC its going to start probing from where the program was launched, and because MSBuild was launched from the %FrameworkDir%/%FrameworkVersion% folder it is unlikely to find the assembly it's looking for.

This explains why you wouldn't see this issue in a console application (the assembly most likely sat right next to the console app)

The solution offered in the MSDN Forum post is also applicable here, basically they added an additional event handler to attempt to probe from a known location, again I have quoted the relevant portions:

For anyone who cares, the workaround is to register a handler for the AppDomain.AssemblyResolve event, and to the Assembly.LoadFrom() there.

Personally this scares me, but it is the only solution I have found that works, a bit more googling hasn't shown me a Microsoft Connect issue for this, but it is most likely not going to be fixed or is by design.

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