2015-10-29 22 views
5

mia app tenta di deserializzare dati inviati dal cliente e non riesce con il seguente errore:Come eseguire il debug (passaggio in) BinaryFormatter.Deserialize()?

Exception thrown: 'System.Runtime.Serialization.SerializationException' in mscorlib.dll

Additional information: Cannot get the member '<.ctor>b__0'.

googling dà alcun risultato. Ok, ho deciso di entrare nella logica della deserializzazione e cercare di capire cosa sta causando esattamente questo. Bene, è passato un giorno e io non sono da nessuna parte vicino.

Ho utilizzato le istruzioni dal sito Web Microsoft Reference Source per configurare Visual Studio. Lo fa a scaricare qualcosa

MicrosoftPublicSymbols\mscorlib.pdb\ 
    DCF1E4D31F6944AC87E7A634262BEE881\mscorlib.pdb (780kb) 
    E47257B512BA49BC9FC367C532FC5F1E2\mscorlib.pdb (953kb) 

ma debugger non si attiva più

Googled sempre trovato un altro modo per farlo -. Installato app dotTrace e used it as source server. E questo non aiuta neanche. Vedo ancora il seguente:

enter image description here

Symbol Load Information comparsa per mscorlib.pdb dice

C:\Users\me\AppData\Local\Temp\SymbolCache\MicrosoftPublicSymbols\mscorlib.pdb\e47257b512ba49bc9fc367c532fc5f1e2\mscorlib.pdb: Symbols loaded.

posso intervenire in System.Windows.Forms, System.Linq, ecc - in modo generale, funziona - solo questa particolare chiamata a BinaryFormatter.Deserialize() non funziona. Quali potrebbero essere le ragioni e come posso farlo entrare?

Potrebbe essere a causa dell'attributo SecuritySafeCritical?

[System.Security.SecuritySafeCritical] 
public Object Deserialize(Stream serializationStream) 

Sto usando VS 2015. Net 4.5.2 (anche se ho provato 4.5 con gli stessi risultati).

+1

Si desidera eseguire il debug del codice Microsoft o per risolvere il problema di deserializzazione? –

+0

Non so come risolvere il mio problema di deserializzazione senza eseguire il debug del codice MS in modo da poter vedere esattamente perché non riesce.Hai suggerimenti migliori? – avs099

+0

Come hai ottenuto i dati serializzati? Puoi creare un esempio più semplice che riproduca il comportamento? –

risposta

8

Senza alcun dettaglio, posso supporre che questo sia un problema di compatibilità con le versioni degli oggetti che si tenta di serializzare & deserializzare. Sembra che il client ti invii dei vecchi bit oggetto (senza lambda nel costruttore). E il tuo server esegue una versione più recente del software alla ricerca di un metodo lambda.

< .ctor> b__0 - è il nome del metodo per il primo metodo lambda in .ctor (costruttore di oggetti).

Così, per esempio, se si ha avuto sulla macchina oggetto del client A:

class A { 
    public A() { 
    int a = 5; 
    int b = 7; 
    // Plain code, no lambdas 
    } 
} 

Poi aggiornati la classe sul server di introdurre lambda nel costruttore:

class A { 
    public A() { 
    int a = 5; 
    int b = 7; 
    Func<int,int> some = x => x * 2 + a; 
    } 
} 

Dopo che la loro rappresentazione binaria non è il lo stesso, la versione server di A ha il metodo invisibile privato < .ctor> b__0 in esso.

Generated IL for lamda method in class A1

+0

beh - un buon lavoro svolto ma sfortunatamente non è così. I file di origine non sono cambiati da anni e non vi sono lambda in essi. – avs099

+0

@ avs099 hai scoperto allora che cos'era? Questo è un buon candidato per un problema simile che sto esaminando. Le fonti non sono cambiate, ma mentre faccio un confronto a livello di assembly, sospetto che l'output di build sia cambiato a causa di un diverso processo di compilazione utilizzato. – eglasius

+0

@eglasius nope, sembrava promettente ma non era il mio caso :(se riesci ad arrivare alla fine di questo, per favore condividi :) – avs099

2

Microsoft non caricare la fonte di ogni aggiornamento mscorlib.dll, questo è il motivo per cui si ottiene solo PDBs pubblici senza dati di origine. Ma c'è un Addon di Visual Studio da Redgate's Reflector dove puoi decompile 3rd party DLLs and step through them in the VS debugger.

enter image description here

enter image description here

DotPeek da JetBrains anche supports PDB generation and hosting of a Symbol server per consentire il debug.

Forse questo ti aiuta a eseguire il debug del tuo problema.

+0

non chiaro - stai dicendo che esiste un PDB pubblico con sorgenti di formattazione binaria ma è per una versione precedente di .net? Dove posso prenderlo allora? re: dotPeek - come ho detto nella mia domanda, l'ho provato ma non è stato d'aiuto. – avs099

+0

nessun PDB pubblico non ha codice sorgente collegato. disinstallare eventuali aggiornamenti .net per tornare alla versione 4.5.2 RTM. Ora è possibile ottenere l'origine PDB privata + dal server di riferimento: http://referencesource.microsoft.com/ – magicandre1981

1

tl; dr: versione diversa di un compilatore (o impostazioni diverse?) Può generare nomi diversi per il metodo generato corrispondente a una funzione anonima. Se un tale metodo viene indirizzato da un campo privato di una classe serializzata, si ottiene l'eccezione, anche se la sorgente non è cambiata tra le 2 build.


Ho appena rintracciato l'esatto tipo di situazione, ma con la deserializzazione innescato nella sessione di un'applicazione asp.net. Come in questo caso, viene utilizzato il BinaryFormatter.

< .ctor> b__0 corrisponde al metodo generato corrispondente a una funzione anonima.

Ora, il problema qui è la dipendenza da un tale metodo durante la serializzazione, perché il nome non è garantito per essere uguale su build differenti (anche con una fonte non modificata). Questo quasi sicuramente traccia per qualche tipo di delegato in un campo di istanza privato di una classe serializzata. Si noti che tale classe in cui viene dichiarata la funzione anonima non è necessariamente la classe che contiene il riferimento a tale funzione in un campo privato.

Purtroppo non ho avuto il tempo di tenere traccia del motivo per cui la stessa fonte produce nomi diversi per la funzione anonima, ma data la storia del progetto coinvolto è una versione del compilatore diversa delle opzioni passate. Sono convinto che sia il precedente.

Se si ha accesso agli assiemi su entrambi i lati, è possibile confermare la modifica. All'inizio ho provato ad esportare la sorgente dissimulata di entrambi gli assembly in DotPeek e poi a fare una differenza tra le cartelle. Questo non è stato un buon processo, ma potrebbe essere dovuto ad alcune impostazioni di DotPeek che devono essere impostate o qualcosa del genere.

Ciò che ha funzionato meglio era l'utilizzo di una combinazione di ndepend e riflettore. È possibile eseguire un confronto di assieme del precedente. Il modo in cui l'ho fatto è stato quello di cambiare una delle build in query per ottenere tutti i costruttori di classi serializzate che avevano qualsiasi tipo di cambiamento. Ciò lo ha ristretto a poche classi/costruttori (c'è il rischio di non prenderlo in questo modo, se la funzione anonima è stata creata in una classe non serializzabile).

Dopo averlo ridotto a pochi costruttori, da ndepend ho aperto un confronto vecchio vs nuovo che utilizza il riflettore per esso. Questo non solo ha mostrato il nome del metodo nello stesso formato dell'eccezione, ma ha già mostrato di aver trovato quello giusto nel codice base.

Una volta aggiornata la classe, ho trovato preferibile aprire ogni assembly in una finestra separata del programma di ricerca e vedere i metodi della classe. È abbastanza visibile lì.

Si noti inoltre che nel caso in cui il codice venga modificato, anche la stessa versione/opzione del compilatore potrebbe dare nomi diversi, quindi è molto fragile avere campi privati ​​in classi serializzabili che puntano a funzioni. La seguente risposta si espande: https://stackoverflow.com/a/1133465/66372