Mam problem z deserializacji XML, który mnie zaskakuje.Dlaczego XmlSerializer.Deserialize rzuca wyjątek System.IO.FileLoadException?
Buduję aplikację, która obsługuje lokalne dostosowywanie różnych usług, z których korzysta. Zaimplementowałem abstrakcyjną klasę ServiceLocator
, której metody zwracają różne obiekty. Każda niestandardowa instalacja jest odpowiedzialna za wdrożenie podklasy tego i dostarczenie implementacji tych metod. Mięso tej klasy wygląda następująco:
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();
}
Działa to dobrze: otrzymuję ścieżka zwyczaju dysponuje zespół z pliku konfiguracyjnego aplikacji, program nazywa Initialize
, a następnie aplikacja może wywołać różne metody na ServiceLocator.Default
i zwracają odpowiednie niestandardowe implementacje usług.
Jedną z tych usług jest DefaultValuesContainer
. Jest to prosty obiekt, który eksponuje właściwości, których wartości należy utrwalić w pliku ustawień użytkownika. Chodzi o to, że mogę przekształcić ten obiekt do postaci pojedynczego użytkownika typu string
. Tworzy plik ustawień użytkownika, którego nie chcesz edytować ręcznie, ale jestem z tym fajny.
Oto konkretna realizacja 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));
}
Teraz tutaj jest rzeczą.
Zbudowałem testy jednostkowe dla tego przy użyciu NUnit. Kiedy przeprowadzam testy w klasie testowej, która obsługuje niestandardowe funkcje klienta, działają. Kiedy uruchomić cały zestaw testów, ostatni wiersz powyższego sposobu rzuca ten wyjątek:
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
mam niby zaskoczony, dlaczego. Metoda SetUp
nadal działa, a ServiceLocator.Default
nadal zwraca obiekt typu ClientServiceLocator
, co oznacza, że załadował on zestaw ClientCustomFeatures
. Rzeczywiście, sama metoda, która rzuca wyjątek, jest w zespole, o którym mówiono, że nie można go załadować.
Co to jest próbowanie zrobić tutaj XmlSerializer
? Dlaczego próbuje załadować zestaw, który jest już załadowany? Co u licha oznacza "Nieprawidłowy wskaźnik"? A nade wszystko jak mam debugować coś takiego?
Nie znam tego konkretnego błędu, ale zauważ, że XmlSerializer używa generowania kodu i kompilacji dynamicznej, więc próbuje utworzyć * nowy * zestaw, który odwołuje się do tych, których potrzebuje. Wygląda na to, że ten nowy (wygenerowany) zestaw nie jest zadowolony z odniesienia. Czy (na przykład) wszystkie niezbędne typy zawierają "publiczny"? –
Jest to z pewnością problem odniesienia. Otwórz plik ClientCustomFeatures.dll w odbłyśniku i wyszukaj odniesienia, których nie masz. –