Yapıcıda FileNotFoundException veren XmlSerializer


347

Türleri serileştirmeye çalıştığımda çalıştığım bir uygulama başarısız oluyor.

Gibi bir ifade

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

üretir:

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)

Sınıfım için özel serileştiriciler tanımlamıyorum.

Bu sorunu nasıl düzeltebilirim?


5
Tamam, bu yüzden bu soru zaten sorulan bir VB sorusunun sadece C # sürümüdür: stackoverflow.com/questions/294659/… Teşekkürler çocuklar.
Irwin

1
Altı yıl sonra, @VladV'nin cevabı en basit ve en az olumsuz etkileyen çözümdür. Generate serialization assemblyAçılır menüyü "Otomatik" yerine "Açık" olarak değiştirmeniz yeterlidir.
Heliac

@Heliac: Kabul etmiyorum. Her zaman çalışmaz. Lütfen Benoit Blanchon'un Vlad'ın cevabı hakkındaki yorumuna bakın. Benim için en basit cevap yapılandırma dosyalarında String.Collection kullanmamaktır. Bunun yerine şunu kullanıyorum: string [] items = Settings.Default.StringofNewlineDelimitedItems.Split (new [] {Environment.NewLine});
Andrew Dennison

Yanıtlar:


388

İster inanın ister inanmayın, bu normal bir davranıştır. Bir istisna atılır, ancak XmlSerializer tarafından işlenir, bu yüzden sadece görmezden gelirseniz her şey yolunda gitmelidir.

Bunu çok sinir bozucu buldum ve biraz etrafta arama yaparsanız bu konuda pek çok şikayet oldu, ancak Microsoft'u okuduğumdan bu konuda bir şey yapmayı planlamıyorum.

Belirli bir istisna için ilk şans istisnalarını kapatırsanız, hata ayıklama sırasında İstisna açılır pencereleri almaktan kaçınabilirsiniz. Visual Studio'da Hata Ayıkla -> Özel Durumlar'a gidin (veya Ctrl+ Alt+ tuşlarına basın E), Ortak Dil Çalışma Zamanı Özel Durumları -> System.IO -> System.IO.FileNotFoundException .

Etrafında başka bir yolla ilgili bilgileri C # XmlSerializer FileNotFound istisnasında (Chris Sells'in aracı XmlSerializerPreCompiler'i tartışır ) bulabilirsiniz.


162
Bu sorundan kurtulmanın olası yollarından biri, Araçlar -> Seçenekler -> Hata Ayıklama -> Genel seçeneklerde "Yalnızca kodum" seçeneğini işaretlemektir.
Frederic

26
@Frederic: Bu yorum harika! Burada bir "WTF !?" yüzümdeki ifade, bu sahte istisnayı avlamaya çalışıyor ve bu soruyu cevapla buluyorum (Microsoft'un hatası, başka ne var?), ancak istisna işlemeyi devre dışı bırakmak istemedim, çünkü buna ihtiyacım olabilir kodum. A +!
Kumba

27
Hans'ın aşağıdaki önerisinin daha değerli olduğunu düşünüyorum - bu istisnayı hiç üretmeyen farklı bir yöntem çağrısı kullanın: XmlSerializer serializer = XmlSerializer.FromTypes (new [] {typeof (MyType)}) [0];
parlak

3
Sorun bu benim test başarısız olur, bu yüzden sadece istisna "görmezden" olamaz
Csaba Toth

16
Üzgünüm, ama bu korkunç bir öneri. FileNotFoundException, deneyimlerime göre daha yaygın olanlardan biridir ve bu istisna raporunu devre dışı bırakmak, bir gün gelecekte sorun istemektedir. 'Sadece Kodum'u açmak veya aşağıda açıklanan serileştirme derlemelerinin oluşturulmasını etkinleştirmek daha iyidir.
Quarkly

104

Martin Sherburn'un dediği gibi, bu normal bir davranış. XmlSerializer'ın kurucusu önce türünüzün serileştirilmesi için oluşturulan sınıfı içermesi gereken [YourAssembly] .XmlSerializers.dll adlı bir derleme bulmaya çalışır. Böyle bir DLL henüz oluşturulmadığından (varsayılan olarak değillerdir), bir FileNotFoundException oluşturulur. Bu olduğunda, XmlSerializer'ın yapıcısı bu özel durumu yakalar ve DLL çalışma zamanında XmlSerializer'ın yapıcısı tarafından otomatik olarak oluşturulur (bu işlem, bilgisayarınızın% temp% dizininde C # kaynak dosyaları üretilip C # derleyicisi kullanılarak derlenerek yapılır). Aynı tür için bir XmlSerializer ek yapılar sadece oluşturulan DLL kullanır.

GÜNCELLEME: NET 4.5'ten başlayarakXmlSerializer , açıkça bir yapılandırma dosyası ayarı ( useLegacySerializerGeneration ) ayarlayarak zorunlu kılınmadıkça, çalışma zamanında bir serileştirici derlemesi oluşturmak için kod oluşturma veya C # derleyicisi ile derleme gerçekleştirmez . Bu değişiklik, bağımlılığı ortadan kaldırır csc.exeve başlangıç ​​performansını artırır. Kaynak: .NET Framework 4.5 Benioku , bölüm 1.3.8.1.

İstisna, XmlSerializer'ın yapıcısı tarafından işlenir. Kendiniz herhangi bir şey yapmanıza gerek yoktur, programınızı yürütmeye devam etmek için 'Devam Et'i (F5) tıklamanız yeterlidir ve her şey yoluna girer. Programınızın yürütülmesini durduran ve bir istisna yardımcısı belirten istisnalardan rahatsızsanız, ya 'Just My Code'unuz kapalıdır ya da FileNotFoundException atıldığında yerine' Kullanıcı- işlenmeyen'.

'Yalnızca Kodum'u etkinleştirmek için Araçlar >> Seçenekler >> Hata Ayıklama >> Genel >> Sadece Kodumu Etkinleştir'e gidin. FileNotFound atıldığında yürütmenin kesilmesini kapatmak için Hata Ayıkla >> Özel Durumlar >> Bul >> girin 'FileNotFoundException' girin >> >> System.IO.FileNotFoundException öğesinden 'Thrown' onay kutusunun işaretini kaldırın.


Güncelleme için +1: Bu, test
senaryolarında

3
Güncelleştirmeniz, bu özel durumun .NET 4.5'te olmaması gerektiğini, ancak yine de görüyorum.
Timbo

@Timbo: .NET 4.5 ile neden bu istisnayı alamadığınızı anlamıyorum. Hala bir dosya arar ve dosya eksikse bir FileNotFoundExceptionatılır. Aradaki fark, montajın varlığının nasıl kontrol edildiği değil, eksik olduğu belirlendikten sonra nasıl oluşturulacağıdır. Daha önce, IL oluşturmak için C # derleyicisine yapılan bir çağrı ile metinsel C # kodu oluşturma kullanılır. .NET 4.5 ile başlayarak, derleyici kullanmadan IL'yi doğrudan yayar.
Allon Guralnek

1
Keşke MS bunu {Load} catch {Fallback} yerine deneyin (File.Exists (...)) {Load} else {Fallback} gibi uygular. İstisna tabanlı akış kontrolü kötü kokuyor ve hata ayıklama deneyimimi gerekenden daha zor ve kırılgan hale getiriyor.
Timbo

1
@Timbo: Bir basit File.Exists()yeterli olmayabilir. Bir montajı bulmak basit bir mesele değildir, çalışma zamanı çeşitli konumlara bakar ve davranışların ortama göre değiştiğine inanıyorum (konsol uygulaması vs IIS'de barındırılıyor vb.). Sanırım neyin uygulanması gerekiyordu TryLoadAssembly()ya da benzer bir şeydi.
Allon Guralnek

63

Visual Studio proje özellikleri ("Oluştur" sayfasında, doğru hatırlıyorum) "serileştirme derleme oluşturmak" diyen bir seçenek vardır. [MyType Montajını İçeren] üreten bir proje için açmayı deneyin .


4
Ayrıca serileştirme düzeneği hala Visual Studio tarafından oluşturulmadıysa stackoverflow.com/a/8798289/1164966 adresine bakın .
Benoit Blanchon

En iyi, en açık, özlü cevap! Keşke tekrar oy verebilsem!
John Zabroski

59

Bunun için bir çözüm var. Eğer kullanırsan

XmlSerializer lizer = XmlSerializer.FromTypes(new[] { typeof(MyType) })[0];

bu istisnayı önlemelidir. Bu benim için çalıştı.

UYARI: Birden çok kez kullanmayın, aksi takdirde bellek sızıntısı olur

XmlSerializerAynı türden birden fazla kez örnek oluşturmak için bu yöntemi kullanırsanız deli gibi bellek sızdırırsınız !

Bunun nedeni, bu yöntemin XmlSerializer(type)ve XmlSerializer(type, defaultNameSpace)yapıcılar tarafından sağlanan yerleşik önbelleği atlamasıdır (diğer tüm kurucular da önbelleği atlar).

Bu iki kurucu aracılığıyla olmayan bir XmlSerializer oluşturmak için herhangi bir yöntem kullanırsanız, kendi önbelleğe alma uygulamanız gerekir yoksa bellek kanama.


44
UYARI:XmlSerializer Aynı türden birden çok kez örnek oluşturmak için bu yöntemi kullanırsanız deli gibi bellek sızdırırsınız ! Bunun nedeni, bu yöntemin XmlSerializer(type)ve XmlSerializer(type, defaultNameSpace)yapıcılar tarafından sağlanan yerleşik önbelleği atlamasıdır (diğer tüm kurucular da önbelleği atlar). XmlSerializerBu iki kurucu ile olmayan bir yöntem oluşturmak için herhangi bir yöntem kullanırsanız , kendi önbelleğe almanızı veya hafızayı kanamanız gerekir.
Allon Güralnek

4
@AllonGuralnek Lanetleneceğim ... kesinlikle haklısın; Reflector ile daha fazla kazma, önbelleği kontrol ederken , serileştirme düzeneğini oluşturduktan sonra bunu yaptığını gösterir ! O ne lan?!?
JerKimball

4
Bilinen bir hata olduğu ortaya çıktı: weblogs.asp.net/cschittko/archive/2005/01/14/353435.aspx
JerKimball

3
@ JerKimball: Bu sayfa aslında yalan söylemiyor. Eğer keşfedilen gibi, FromTypesönbelleği doldurmak için görünmüyor. Bu nedenle XmlSerializer, bir ifadede boş bir önbelleği ısıtmak için geçerli bir yol olmalı (makalenin önerdiği gibi), ancak ondan bir şey almanın gerçekten kötü bir yolu olmalı (sadece en basit kurucular aracılığıyla yapılmalıdır). Her halükarda, bunun bir hata olduğunu bilmiyordum, her zaman sızıntıların sızıntı yapması gerektiğini düşündüm (daha gelişmiş XmlSerializerkurucular gibi). FromTypes()Sadece yapabileceğiniz için kullanmayı düşünmezdim bile types.Select(t => new XmlSerializer(t)).
Allon Güralnek

2
@AllonGuralnek Kullanmanın araştırılmayan yönü FromTypescazibesine sahiptir - atılan istisnalar bile yakalansa bile, pahalı bir işlemdir; 'Kendi yolunuzu önbellekleyin' yaklaşımı, tek resmi çözüm olarak görünmektedir, çünkü resmi olarak desteklenen tek düzeltme belirsiz bir web tabanlı derlemede görünmektedir. (edit: açıkçası, ben her şeyi veri sözleşmelerine taşımak için ben :))
JerKimball

23

Bu sorunla karşılaştım ve bahsi geçen çözümlerin hiçbiri ile başa çıkamadım.

Sonra sonunda bir çözüm buldum. Serileştiricinin sadece türe değil, aynı zamanda iç içe tiplere de ihtiyacı olduğu görülmektedir. Bunu değiştirme:

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

Buna:

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

Sorun benim için düzeltildi. Artık istisna falan yok.


8
Bu benim için çalıştı. Net4.0 kullanarak biçimvar xmlSerializer = new XmlSerializer(typeof(T), typeof(T).GetNestedTypes());
user3161729

1
Bu benim için de işe yaradı. Ancak serileştirmeyi değil serileştirmeyi gerektirir. Belki mantıklı, belki de mantıklı değil.
SteveCinq

2
Bu, birçok kez çalıştırılırsa bellek sızıntısı da üretir.
Volodymyr Kotylo

9

Benim çözüm serileştirici oluşturmak için doğrudan yansıma gitmek. Bu, özel duruma neden olan garip dosya yüklemesini atlar. Bunu serileştiricinin önbelleğe alınmasını da sağlayan bir yardımcı işlevde paketledim.

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;
    }
}

Burada 2 sorun var - önce kodunuz iş parçacığı için güvenli değil ve ikincisi (daha da önemlisi) .net çalışma zamanının zaten ne yaptığını (kullanmaya çalıştığınız ctor'a göre) çoğaltmaya çalışıyorsunuz. yani bu koda gerek yoktur
Dave Black

@DaveBlack: Evet, quadfinity'in bir ConcurrentDictionary için önbellekleme ile cevabı daha iyi olurdu
d - b

@db 2nci nokta, önbelleklemenin bile gerekli olmadığıydı - çerçeve önbelleğe aldığı 2 ctordan birini kullandığınız sürece (OP ilkini kullanıyor). MSDN'den: Performansı artırmak için, XML serileştirme altyapısı, belirtilen türlerin serileştirilmesi ve serileştirilmesi için derlemeler oluşturur. Çerçeve bu meclisleri bulur ve yeniden kullanır. Bu davranış, yalnızca aşağıdaki ctors kullanılırken oluşur: XmlSerializer.XmlSerializer (Tür) XmlSerializer.XmlSerializer (Tür, Dize) Başvuru: msdn.microsoft.com/en-us/library/…
Dave Black

@DaveBlack: Evet, ancak bu yapıcılar kullanım tamamen geçerli olsa bile dahili olarak bir istisna atar ve yakalar. Bu kötü ve OP'nin ilk etapta soruyu sormasının nedeni bu.
d - b

@db Doğru, ama demek istediğim (ama açık değildi - özür dilerim), solnunuzun gerekli olan tek satırının diğer durumdaki ilk 3 satır olmasıydı.
Dave Black

8

İstisnadan kaçınmak için iki şey yapmanız gerekir:

  1. Serileştirilmiş sınıfa bir özellik ekleyin (umarım erişiminiz olur)
  2. Sgen.exe ile serileştirme dosyası oluşturun

Sınıfınıza System.Xml.Serialization.XmlSerializerAssembly özniteliğini ekleyin. 'MyAssembly' öğesini MyClass'ın bulunduğu derlemenin adıyla değiştirin.

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

}

Serileştirme dosyasını sgen.exe yardımcı programını kullanarak oluşturun ve sınıfın derlemesiyle dağıtın.

'sgen.exe MyAssembly.dll' MyAssembly.XmlSerializers.dll dosyasını oluşturur

Bu iki değişiklik, .net'in doğrudan derlemeyi bulmasına neden olur. Ben kontrol ettim ve Visual Studio 2008 ile .NET framework 3.5 üzerinde çalışıyor


Tamam, ve bu değişiklikler olmadan başarısız oldu ve eğer öyleyse, neden?
John Saunders

1
VS2012'deki 4.0 projemin aniden başarısız olmaya başlamasının bir nedenini bulamıyorum. Active Directory'ye her erişmeye çalıştığımda bu hata "yok sayılıyor" bir seçenek değildi; dolayısıyla görmezden gelmek kimlik doğrulamamak anlamına gelir. Hala VS2012 otomatik olarak serileştirme DLL düzgün oluşturmak olmaz sinirli. Ancak, bu adımlar mükemmel çözümü sağlamıştır.
sfuqua

6

Bu istisna, BindingFailure adlı yönetilen bir hata ayıklama yardımcısı (MDA) tarafından da yakalanabilir .

Bu MDA, uygulamanız önceden derlenmiş serileştirme montajlarıyla birlikte gönderilecek şekilde tasarlanmışsa kullanışlıdır. Uygulamamızın performansını artırmak için bunu yapıyoruz. Önceden oluşturulmuş serileştirme montajlarının derleme sürecimiz tarafından düzgün bir şekilde inşa edildiğinden ve uygulama tarafından anında yeniden yüklenmeden yüklendiğinden emin olmamızı sağlar.

Bu senaryo dışında gerçekten yararlı değil, çünkü diğer posterlerin söylediği gibi, bir bağlayıcı hata Serializer yapıcısı tarafından yakalandığında, serileştirme düzeneği çalışma zamanında yeniden oluşturulur. Böylece genellikle kapatabilirsiniz.


6

XmlSerializer.FromTypes işlevi özel durumu atmıyor, ancak belleği sızdırıyor. Bu nedenle, oluşturulan her örnek için bellek sızıntısını önlemek için bu tür bir serileştiriciyi her tür için önbelleğe almanız gerekir.

Kendi XmlSerializer fabrikanızı oluşturun ve basitçe kullanın:

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

Fabrika gibi görünüyor:

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;
    }       
}

Bellek sızıntısı olasılığı olmayan daha karmaşık sürüm (lütfen birisi kodu inceleyin):

    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;
    }       
}

Bunun yerine ConcurrentDictionary kullanmalısınız. Bu kod kilitlenebilir.
Behrooz

Sözlük ile tüm yönetim kilit bölümünde ise nasıl kilitlenebilir?
Tomas Kubes

Üzgünüm, kelimeler karıştı. Demek istediğim, birden fazla öğe ekleyebiliyor olması. çünkü mevcut olup olmadığını kontrol ettiği zaman ve yerleştirdiği zaman arasında bir boşluk vardır. eşzamanlı sözlük bir tür iki fazlı kilitleme kullanır (torba [0] ve ardından torba [hash]]) ve çalıştığınız öğeyi eklemesi / içermesi gereken torbaya bir referans tutar. Daha hızlı, daha güvenli ve daha temiz.
Behrooz

Evet ve hayır. Aynı zamanda, iki tipte paralel olarak aynı türden bir serileştiricinin oluşturulacağı ve daha sonra sözlüğe iki kez eklenebileceği haklısınız. Böyle bir durumda ikinci kesici uç birincisinin yerini alacaktır, ancak kilit bölümü iplik güvenliğini garanti eder ve genel dezavantaj küçük bellek sızıntısıdır. Bu performans optimizasyonudur, çünkü A tipi Serializer ile bir iplik istemiyorsanız, gerçek senaryoda B tipi serileştirici ile ikinci iplik tarafından engellenmesini bekleyin.
Tomas Kubes

Çözümü daha iyi (teorik bellek sızıntısı olmadan), ancak daha karmaşık olabileceğini hayal edebiliyorum.
Tomas Kubes

3

Öte yandan derleme hatalarının giderilmesi çok karmaşıktır. Bu sorunlar kendilerini bir FileNotFoundException iletisi ile kendini gösterir:

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() 

Bir serileştirici nesnesinin somutlaştırılmasıyla istisna bulunmayan bir dosyanın ne yapacağını merak edebilirsiniz, ancak unutmayın: yapıcı C # dosyalarını yazar ve bunları derlemeye çalışır. Bu istisnanın çağrı yığını, bu şüpheyi desteklemek için bazı iyi bilgiler sağlar. XmlSerializer, System.Reflection.Assembly.Load yöntemini çağıran CodeDOM tarafından oluşturulan bir derleme yüklemeye çalışırken istisna oluştu. İstisna, XmlSerializer'ın oluşturması gereken derlemenin neden mevcut olmadığına dair bir açıklama sağlamaz. Derleme başarısız olduğu için genel olarak derleme bulunmaz, bu nadir durumlarda C # derleyicisinin derleyemediği kod ürettiği için nadiren de olabilir.

Not Bu hata, XmlSerializer geçici dizine erişemeyen bir hesap veya güvenlik ortamında çalıştığında da oluşur.

Kaynak : http://msdn.microsoft.com/en-us/library/aa302290.aspx


bunun çalışma zamanında olduğunu belirtmedi. Aklıma gelen başka bir şey, belki de bir isim-alanı / sınıf çatışması olması. MyType'ınızın tam adı nedir?
Zyphrax

Evet, ur link kontrol, yararlı olsa da, inşaatçılar hakkında bilgi, ne ı gerek değildi.
Irwin

5
@SpaceghostAl Çalışma zamanında derleyebilirsiniz. Ve XmlSerializer bunu yapar. Çalışma zamanında dinamik olarak, belirli bir tür için XML serileştiren (de) bir derleme oluşturur. Hangi nedenle olursa olsun, bu süreç OP için başarısız olur. Muhtemelen örneğin geçici bir dizinde izin sorunları nedeniyle. (Hatta disk alanı kadar aptal olabilir.)
nos

Bundan emin misin? Serileştirme şeyler derleme sırasında derleme değil, YourAssemblyName.XmlSerializers.dll adlı bir derleme içine derlendi oldukça emindim . Bu, dağıtım klasöründeki tüm NTFS izinlerinden en azından her türlü nedenden dolayı başarısız olabilir.
tomfanning

1
Keşke bunu birden fazla kez değerlendirebilseydim. Hesabın geçici klasöre erişememesi ile ilgili notunuz benim için yanıtı tetikledi. Hizmet hesabımı sunucudaki yönetici grubuna ekledikten sonra işe yaradı. Teşekkür ederim!
Bob Horn

2

Visual Studio proje özelliklerinde "serileştirme derlemesi oluştur" diyen bir seçenek vardır. [MyType Montajını İçeren] üreten bir proje için açmayı deneyin.


1

Serileştirilecek özel bir sınıf:

[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;
    }
}

Kod pasajını ekledim. Belki bu size yardımcı olabilir.

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();
}

2
Kaynak sızıntılarını önlemek için blok kullanmamak ve XmlTextWriter kullanmak için -1.
John Saunders

Tamam katılıyorum, ama yine de XmlSerializer xmlSerializer = new XmlSerializer (typeof (TestClass)) kullandım; ama ben bu istisnayı alamıyorum.
shahjapan

1

Benzer bir sorunum vardı ve istisnayı görmezden gelmek benim için işe yaramadı. Kodum NServiceBus'un yapılandırmasını çağırıyorduConfigure.With(...).XmlSerializer()...

Benim için sabitleyen şey, projem için platformu değiştirmekti.

  1. Build \ Configuration Manager'a gidin ...
  2. Projenizi bulun ve Platformu değiştirin (benim durumumda x86'dan Herhangi Bir CPU'ya)

1

Referans olarak. DB cevap ve yorumlarından alarak, DB çözüm yakın olan bu çözüm ile geldi. Tüm vakalarımda iyi çalışıyor ve iplik güvenli. Bir ConcurrentDictionary kullanarak Tamam olurdu sanmıyorum.

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;
            }
        }
    }
}

Kullanımı:

        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);
                }
            }
        }

0

Türünüz, ne GAC'de ne de yerel bin klasörünüzde bulunamayan diğer derlemelere başvurabilir ==> ...

"veya bağımlılıklarından biri. Sistem belirtilen dosyayı bulamıyor"

Serileştirmek istediğiniz türden bir örnek verebilir misiniz?

Not: Türünüzün Serializable kullandığından emin olun.


0

Aynı hatayı alıyordum ve bunun nedeni, varsayılan parametresiz bir kurucuya sahip olmamaya çalıştığım seriyi kaldırmaktı . Bir kurucu ekledim ve çalışmaya başladı.


0

XSD'den Sınıf oluşturmak için bir 3. Parti aracı kullanana kadar aynı sorunu yaşadım ve işe yaradı! Aracın sınıfımın üstüne ekstra kod eklediğini keşfettim. Aynı kodu orijinal sınıfımın üstüne eklediğimde işe yaradı. İşte eklediklerim ...

#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

Kullanmak için birçok öneri gördüm ConcurrentDictionary, ancak bunun somut örnekleri yok, bu yüzden şapkamı bu çözüm yarışına atacağım. Ben iş parçacığı için güvenli bir geliştirici değilim, bu yüzden bu kod sağlam değilse, sonra takip edenler uğruna konuşun lütfen.

public static class XmlSerializerHelper
{
    private static readonly ConcurrentDictionary<Type, XmlSerializer> TypeSerializers = new ConcurrentDictionary<Type, XmlSerializer>();

    public static XmlSerializer GetSerializer(Type type)
    {
        return TypeSerializers.GetOrAdd(type,
        t =>
        {
            var importer = new XmlReflectionImporter();
            var mapping = importer.ImportTypeMapping(t, null, null);
            return new XmlSerializer(mapping);
        });
    }
}

Değeri içeren ConcurrentDictionaryve Lazyyükleyen başka gönderiler gördüm . Burada alakalı olup olmadığından emin değilim, ama bunun kodu:

private static readonly ConcurrentDictionary<Type, Lazy<XmlSerializer>> TypeSerializers = new ConcurrentDictionary<Type, Lazy<XmlSerializer>>();

public static XmlSerializer GetSerializer(Type type)
{
    return TypeSerializers.GetOrAdd(type,
    t =>
    {
        var importer = new XmlReflectionImporter();
        var mapping = importer.ImportTypeMapping(t, null, null);
        var lazyResult = new Lazy<XmlSerializer>(() => new XmlSerializer(mapping), LazyThreadSafetyMode.ExecutionAndPublication);
        return lazyResult;
    }).Value;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.