我对XML反序列化有一个困扰,这使我感到困惑。

我正在构建一个支持本地使用的各种服务的自定义应用程序。我实现了一个抽象的ServiceLocator类,该类的方法返回各种对象。每个自定义安装负责实现该方法的子类并提供这些方法的实现。这个类的肉看起来像这样:

public abstract class ServiceLocator
{
    public static void Initialize(string customFeaturesPath)
    {
        Assembly a = Assembly.LoadFrom(customFeaturesPath);
        Type t = a.GetExportedTypes()
            .AsEnumerable()
            .Where(x => x.IsSubclassOf(typeof (ServiceLocator)))
            .First();
        Default = (ServiceLocator)a.CreateInstance(t.FullName);
    }

    public static ServiceLocator Default { get; private set; }

    public abstract DefaultValuesContainer CreateDefaultValuesContainer();
}

这很好用:我从应用程序配置文件中获得了自定义功能部件程序集的路径,程序调用了Initialize,然后应用程序可以调用ServiceLocator.Default上的各种方法,并且它们返回服务的适当的自定义实现。

这些服务之一是DefaultValuesContainer。这是一个简单的对象,它公开需要在用户设置文件中保留其值的属性。我的想法是,我可以将该对象序列化为string类型的单个用户设置。它使您不需要手动编辑用户设置文件,但是我对此很满意。

这是ServiceLocator.CreateDefaultValuesContainer的具体实现:
protected override DefaultValuesContainer CreateDefaultValuesContainer(string serializedXml)
{
    DefaultValuesContainer c = new ClientDefaultValuesContainer();

    if (string.IsNullOrEmpty(serializedXml))
    {
        return c;
    }
    XmlSerializer x = new XmlSerializer(c.GetType());
    return (DefaultValuesContainer) x.Deserialize(new StringReader(serializedXml));
}

现在是这样。

我已经使用NUnit构建了单元测试。当我在行使客户自定义功能的测试装置类中运行测试时,它们将起作用。当我运行整个测试套件时,上述方法的最后一行抛出此异常:
System.InvalidOperationException : There is an error in XML document (0, 0).
  ----> System.IO.FileLoadException : Could not load file or assembly 'ClientCustomFeatures, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. Invalid pointer (Exception from HRESULT: 0x80004003 (E_POINTER))
  ----> System.ArgumentNullException : Value cannot be null.
Parameter name: path1

我对为什么感到困惑。 SetUp方法仍然运行,并且ServiceLocator.Default仍然返回ClientServiceLocator类型的对象,这意味着它已经加载了ClientCustomFeatures程序集。确实,引发异常的方法恰恰是在被告知无法加载的程序集中。
XmlSerializer在这里试图做什么?为什么要尝试加载已经加载的程序集? “无效指针”到底是什么意思?最重要的是,我应该如何调试类似的东西?

最佳答案

如果您的自定义程序集不知道将包含ClientCustomFeatures类的程序集加载到何处,则会发生这种情况。当您将自定义装配体部署到不在主装配体路径中且主装配体不在gac中的位置时,就会发生这种情况。因此,如果您的自定义装配体是从主装配体的子目录中加载的,则该装配体将消失。但是,如果它们位于任意位置,则会遇到问题,因为它们需要加载您的主程序集,因为它们需要访问ClientCustomFeatures类型。

10-02 14:50