XmlSerializer daje FileNotFoundException w konstruktorze

Aplikacja, z którą pracowałem, zawodzi, gdy próbuję serializować typy.

A statement like

XmlSerializer lizer = new XmlSerializer(typeof(MyType));

Produkuje:

System.IO.FileNotFoundException occurred
  Message="Could not load file or assembly '[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified."
  Source="mscorlib"
  FileName="[Containing Assembly of MyType].XmlSerializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
  FusionLog=""
  StackTrace:
       at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
       at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
Nie definiuję żadnych specjalnych seriali dla mojej klasy.

Jak mogę rozwiązać ten problem?

Author: Peter Mortensen, 2009-07-14

17 answers

Wierz lub nie, to normalne zachowanie. Wyjątek jest wyrzucany, ale obsługiwany przez XmlSerializer, więc jeśli go zignorujesz, wszystko powinno działać dobrze.

Znalazłem to bardzo niepokojące, i było wiele skarg na to, jeśli szukasz trochę, ale z tego, co czytałem Microsoft nie planuje nic z tym zrobić.

Możesz uniknąć wyświetlania wyskakujących okienek WYJĄTKÓW podczas debugowania, jeśli wyłączysz wyjątki pierwszej szansy szczególny wyjątek. W Visual Studio przejdź do Debug -> wyjątki (lub naciśnij Ctrl + Alt + E), wyjątki w środowisku uruchomieniowym Common Language -> System.IO -> System. IO. FileNotFoundException .

Możesz znaleźć informacje o innym sposobie obejścia go w poście na bloguwyjątek C# XmlSerializer FileNotFound (Chris Sells ' tool XmlSerializerPreCompiler ).

 345
Author: Martin Sherburn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-02 09:47:53

Jak powiedział Martin Sherburn, to normalne zachowanie. Konstruktor XmlSerializer najpierw próbuje znaleźć Zestaw o nazwie [YourAssembly].XmlSerializers.dll, który powinien zawierać wygenerowaną klasę serializacji Twojego typu. Ponieważ taka biblioteka DLL nie została jeszcze wygenerowana (nie są one domyślnie), wyrzucany jest wyjątek FileNotFoundException. Gdy tak się stanie, konstruktor XmlSerializer wychwytuje ten wyjątek, a DLL jest generowany automatycznie w czasie wykonywania przez XmlSerializer konstruktor (odbywa się to poprzez generowanie plików źródłowych C# w katalogu %temp% komputera, a następnie kompilowanie ich przy użyciu kompilatora C#). Dodatkowe konstrukcje Xmlserializera dla tego samego typu będą po prostu używać już Wygenerowanej biblioteki DLL.

UPDATE: począwszy od. NET 4.5, XmlSerializer nie wykonuje już generowania kodu ani kompilacji z kompilatorem C# w celu utworzenia zestawu serializera w czasie wykonywania, chyba że jest to wyraźnie wymuszone przez ustawienie ustawienie pliku konfiguracyjnego (useLegacySerializerGeneration ). Ta zmiana usuwa zależność od csc.exe i poprawia wydajność uruchamiania. Źródło: . NET Framework 4.5 Readme , sekcja 1.3.8.1.

Wyjątek jest obsługiwany przez konstruktor XmlSerializer. Nie ma potrzeby robienia czegokolwiek samemu, możesz po prostu kliknąć "Kontynuuj" (F5), aby kontynuować wykonywanie programu i wszystko będzie dobrze. Jeśli przeszkadzają ci wyjątki podczas wykonywania programu i wyświetlania helpera WYJĄTKÓW, albo masz wyłączony "tylko Mój kod", albo masz ustawiony FileNotFoundException, aby przerwać wykonywanie podczas rzucania, zamiast gdy "użytkownik-unhandled".

Aby włączyć "tylko Mój kod", przejdź do Narzędzia >> Opcje >> debugowanie >> ogólne >> Włącz tylko Mój kod. Aby wyłączyć przerywanie wykonywania podczas wyrzucania pliku FileNotFound, przejdź do debugowania > > wyjątki > > Znajdź > > wpisz "FileNotFoundException" > > odznacz pole wyboru "wyrzucony" z System. IO. FileNotFoundException.

 95
Author: Allon Guralnek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-31 18:32:01

W Visual Studio project properties (strona "Build", o ile dobrze pamiętam) znajduje się opcja "generate serialization assembly". Spróbuj włączyć go dla projektu, który generuje [zawierający Assembly of MyType] .

 61
Author: VladV,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-20 20:28:55

Istnieje obejście tego problemu. Stosowanie

XmlSerializer lizer = XmlSerializer.FromTypes(new[] { typeof(MyType) })[0];
Należy unikać tego wyjątku. To mi pomogło.

Ostrzeżenie: nie używaj wiele razy, bo będziesz miał wyciek pamięci

Będziesz wyciekać pamięć jak szalony, jeśli użyjesz tej metody do tworzenia instancji XmlSerializer dla tego samego typu więcej niż raz!

Dzieje się tak, ponieważ ta metoda omija wbudowane buforowanie pod warunkiem konstruktorów XmlSerializer(type) i XmlSerializer(type, defaultNameSpace) (wszystkie inne konstruktory również ominąć pamięć podręczną).

Jeśli użyjesz jakiejkolwiek metody do stworzenia Xmlserializera, który nie jest za pomocą tych dwóch konstruktorów, musisz zaimplementować własne buforowanie, inaczej będziesz miał pamięć podręczną.

 54
Author: quadfinity,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-22 21:58:13

Natknąłem się na ten problem i nie mogłem go obejść przez żadne z wymienionych rozwiązań.

W końcu znalazłem rozwiązanie. Wygląda na to, że serializator potrzebuje nie tylko typu, ale również zagnieżdżonych typów. Zmiana tego:
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));

Do tego:

XmlSerializer xmlSerializer = new XmlSerializer(typeof(T).GetNestedTypes());

Naprawiono problem dla mnie. Żadnych WYJĄTKÓW.

 18
Author: Frosty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-27 07:27:03

Moim rozwiązaniem jest przejście od razu do refleksji, aby stworzyć serializer. To omija dziwne ładowanie plików, które powoduje wyjątek. Spakowałem to w funkcję pomocnika, która również zajmuje się buforowaniem serializera.

private static readonly Dictionary<Type,XmlSerializer> _xmlSerializerCache = new Dictionary<Type, XmlSerializer>();

public static XmlSerializer CreateDefaultXmlSerializer(Type type) 
{
    XmlSerializer serializer;
    if (_xmlSerializerCache.TryGetValue(type, out serializer))
    {
        return serializer;
    }
    else
    {
        var importer = new XmlReflectionImporter();
        var mapping = importer.ImportTypeMapping(type, null, null);
        serializer = new XmlSerializer(mapping);
        return _xmlSerializerCache[type] = serializer;
    }
}
 9
Author: d--b,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-23 16:16:20

Aby uniknąć wyjątku, musisz zrobić dwie rzeczy:

  1. Dodaj atrybut do klasy serialized (mam nadzieję, że masz dostęp)
  2. Wygeneruj plik serializacji za pomocą sgen.exe

Dodaj System.Xml.Serializacja.Atrybut xmlserializerassembly do twojej klasy. Zastąp "MyAssembly" nazwą zespołu, w którym znajduje się MyClass.

[Serializable]
[XmlSerializerAssembly("MyAssembly.XmlSerializers")]
public class MyClass
{
…
}

Wygeneruj plik serializacji za pomocą sgen.narzędzia exe i wdrożyć go z klasą montaż.

" sgen.exe MyAssembly.dll ' wygeneruje plik MyAssembly.XmlSerializers.dll

Te dwie zmiany spowodują, że. NET bezpośrednio znajdzie asemblację. Sprawdziłem i działa na. Net framework 3.5 z Visual Studio 2008

 7
Author: Ami Bar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-29 12:53:10

Ten wyjątek może być również uwięziony przez managed debugging assistant (MDA) o nazwie BindingFailure.

Ten MDA jest przydatny, jeśli aplikacja jest zaprojektowana do wysyłki z wstępnie zbudowanymi złożeniami serializacji. Robimy to, aby zwiększyć wydajność naszej aplikacji. Pozwala nam to upewnić się, że wstępnie zbudowane zespoły serializacji są prawidłowo budowane przez nasz proces budowania i ładowane przez aplikację bez ponownego budowania w locie.

It ' s really not useful z wyjątkiem tego scenariusza, ponieważ jak powiedziały inne plakaty, gdy konstruktor Serializera uwięzi błąd wiązania, Zespół serializacji jest ponownie budowany w czasie wykonywania. Więc zazwyczaj można go wyłączyć.

 6
Author: HiredMind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-13 19:26:43

Funkcja XmlSerializer.FromTypes nie wyrzuca wyjątku, ale wycieka pamięć. Dlatego musisz buforować taki serializer dla każdego typu, aby uniknąć wycieku pamięci dla każdego utworzonego wystąpienia.

Stwórz własną fabrykę XmlSerializer i użyj jej po prostu:

XmlSerializer serializer = XmlSerializerFactoryNoThrow.Create(typeof(MyType));

Fabryka wygląda tak:

public static class XmlSerializerFactoryNoThrow
{
    public static Dictionary<Type, XmlSerializer> _cache = new Dictionary<Type, XmlSerializer>();

    private static object SyncRootCache = new object();        

    /// <summary>
    /// //the constructor XmlSerializer.FromTypes does not throw exception, but it is said that it causes memory leaks
    /// http://stackoverflow.com/questions/1127431/xmlserializer-giving-filenotfoundexception-at-constructor
    /// That is why I use dictionary to cache the serializers my self.
    /// </summary>
    public static XmlSerializer Create(Type type)
    {
        XmlSerializer serializer;

        lock (SyncRootCache)
        {
            if (_cache.TryGetValue(type, out serializer))
                return serializer;
        }

        lock (type) //multiple variable of type of one type is same instance
        {
            //constructor XmlSerializer.FromTypes does not throw the first chance exception           
            serializer = XmlSerializer.FromTypes(new[] { type })[0];
            //serializer = XmlSerializerFactoryNoThrow.Create(type);
        }

        lock (SyncRootCache)
        {
            _cache[type] = serializer;
        }
        return serializer;
    }       
}

Bardziej skomplikowana wersja bez możliwości wycieku pamięci (proszę o zapoznanie się z kodem):

    public static XmlSerializer Create(Type type)
    {
        XmlSerializer serializer;

        lock (SyncRootCache)
        {
            if (_cache.TryGetValue(type, out serializer))
                return serializer;
        }

        lock (type) //multiple variable of type of one type is same instance
        {
            lock (SyncRootCache)
            {
                if (_cache.TryGetValue(type, out serializer))
                    return serializer;
            }
            serializer = XmlSerializer.FromTypes(new[] { type })[0];
            lock (SyncRootCache)
            {
                _cache[type] = serializer;
            }
        }          
        return serializer;
    }       
}
 6
Author: qub1n,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-23 15:39:27

Rozwiązywanie błędów kompilacji z drugiej strony jest bardzo skomplikowane. Problemy te przejawiają się w FileNotFoundException z Komunikatem:

File or assembly name abcdef.dll, or one of its dependencies, was not found. File name: "abcdef.dll"
   at System.Reflection.Assembly.nLoad( ... )
   at System.Reflection.Assembly.InternalLoad( ... )
   at System.Reflection.Assembly.Load(...)
   at System.CodeDom.Compiler.CompilerResults.get_CompiledAssembly() 

Możesz się zastanawiać, co wyjątek nie znaleziony ma wspólnego z tworzeniem instancji obiektu serializer, ale pamiętaj: konstruktor pisze pliki C# i próbuje je skompilować. Stos wywołań tego wyjątku dostarcza dobrych informacji na poparcie tego podejrzenia. Wyjątek wystąpił podczas próby XmlSerializer aby załadować zestaw wygenerowany przez CodeDOM wywołujący System.Odbicie.Montaż.Metoda ładowania. Wyjątek nie wyjaśnia, dlaczego zgromadzenie, które XmlSerializer miał utworzyć, nie było obecne. Ogólnie rzecz biorąc, asemblacja nie jest obecna, ponieważ kompilacja nie powiodła się, co może się zdarzyć, ponieważ w rzadkich przypadkach atrybuty serializacji wytwarzają kod, którego kompilator C# nie kompiluje.

Uwaga Ten błąd występuje również, gdy XmlSerializer działa w ramach Konta lub środowiska bezpieczeństwa, które nie ma dostępu do katalogu tymczasowego.

Źródło : http://msdn.microsoft.com/en-us/library/aa302290.aspx

 3
Author: Zyphrax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-14 19:26:07

We właściwościach projektu Visual Studio znajduje się opcja "Generuj montaż serializacji". Spróbuj włączyć go dla projektu, który generuje [zawierający Assembly of MyType].

 2
Author: Pascal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-09 08:17:56

Klasa niestandardowa do serializacji:

[Serializable]
public class TestClass
{
    int x = 2;
    int y = 4;
    public TestClass(){}
    public TestClass(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    public int TestFunction()
    {
        return x + y;
    }
}

Załączyłem fragment kodu. Może to ci pomoże.

static void Main(string[] args)
{
    XmlSerializer xmlSerializer = new XmlSerializer(typeof(TestClass));

    MemoryStream memoryStream = new MemoryStream();
    XmlTextWriter xmlWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);

    TestClass domain = new TestClass(10, 3);
    xmlSerializer.Serialize(xmlWriter, domain);
    memoryStream = (MemoryStream)xmlWriter.BaseStream;
    string xmlSerializedString = ConvertByteArray2Str(memoryStream.ToArray());

    TestClass xmlDomain = (TestClass)DeserializeObject(xmlSerializedString);

    Console.WriteLine(xmlDomain.TestFunction().ToString());
    Console.ReadLine();
}
 1
Author: shahjapan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-13 19:22:28

Miałem podobny problem i ignorowanie wyjątku nie zadziałało na mnie. Mój kod wywoływał konfigurację NServiceBus Configure.With(...).XmlSerializer()...

To, co mnie naprawiło, to zmiana platformy dla mojego projektu.

  1. Przejdź do Build \ Configuration Manager...
  2. Znajdź swój projekt i zmień platformę (w moim przypadku z X86 na dowolny procesor)
 1
Author: kkelley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-08 12:19:27

Jako odniesienie. Biorąc od odpowiedzi i komentarzy D-B, przyszedłem z tym rozwiązaniem, które jest bliskie rozwiązaniu D-B. Działa dobrze we wszystkich moich przypadkach i jest bezpieczny dla nici. Nie wydaje mi się, żeby użycie współbieżności było ok.

using System;
using System.Collections.Generic;
using System.Xml.Serialization;

namespace HQ.Util.General
{
    public class XmlSerializerHelper
    {
        private static readonly Dictionary<Type, XmlSerializer> _dictTypeToSerializer = new Dictionary<Type, XmlSerializer>();

        public static XmlSerializer GetSerializer(Type type)
        {
            lock (_dictTypeToSerializer)
            {
                XmlSerializer serializer;
                if (! _dictTypeToSerializer.TryGetValue(type, out serializer))
                {
                    var importer = new XmlReflectionImporter();
                    var mapping = importer.ImportTypeMapping(type, null, null);
                    serializer = new XmlSerializer(mapping);
                    return _dictTypeToSerializer[type] = serializer;
                }

                return serializer;
            }
        }
    }
}

Użycie:

        if (File.Exists(Path))
        {
            using (XmlTextReader reader = new XmlTextReader(Path))
            {
                // XmlSerializer x  = new XmlSerializer(typeof(T));
                var x = XmlSerializerHelper.GetSerializer(typeof(T));

                try
                {
                    options = (OptionsBase<T>)x.Deserialize(reader);
                }
                catch (Exception ex)
                {
                    Log.Instance.AddEntry(LogType.LogException, "Unable to open Options file: " + Path, ex);
                }
            }
        }
 1
Author: Eric Ouellet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-24 18:23:53

Twój typ może odwoływać się do innych zestawów, których nie można znaleźć ani w GAC, ani w lokalnym folderze bin ==> ...

" lub jedną z jego zależności. System nie można znaleźć określonego pliku "

Czy możesz podać przykład typu, który chcesz serializować?

Uwaga: Upewnij się, że Twój typ implementuje Serializowalny.

 0
Author: Henrik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-13 19:21:19

Otrzymywałem ten sam błąd, i to z powodu typu, który próbowałem deserializować, nie mając domyślnego konstruktora bez parametru . Dodałem konstruktor i zaczął działać.

 0
Author: kay.one,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-13 19:28:56

Miałem ten sam problem, dopóki nie użyłem narzędzia 3rd Party do generowania klasy z XSD i to działało! Odkryłem, że narzędzie dodawało dodatkowy kod na szczycie mojej klasy. Kiedy dodałem ten sam kod do góry mojej oryginalnej klasy to działało. Oto co dodałem...

#pragma warning disable
namespace MyNamespace
{
  using System;
  using System.Diagnostics;
  using System.Xml.Serialization;
  using System.Collections;
  using System.Xml.Schema;
  using System.ComponentModel;
  using System.Xml;
  using System.Collections.Generic;

  [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.6.1064.2")]
  [System.SerializableAttribute()]
  [System.Diagnostics.DebuggerStepThroughAttribute()]
  [System.ComponentModel.DesignerCategoryAttribute("code")]
  [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
  [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
  public partial class MyClassName
  {
  ...
 0
Author: TheJonz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-24 17:40:59