2013-02-20 11 views
6

Znalazłem wiele wątków na ten temat, ale nie sądzę, że znalazłem jeden, który ma zastosowanie.System.Runtime.Serialization.SerializationException: Nie można znaleźć zespołu MyAssembly

Zasadniczo mój plik .exe ładuje plik .dll (MyAssembly), który wykonuje serializację i ładowanie. Oczywiście serializuje całkiem dobrze.

Ale kiedy idę do deserializacji pliku w pliku MyAssembly.dll, wybucha z błędem w tytule tego wpisu.

Ktoś ma jakieś pomysły? Nie rozumiem, jak nie może znaleźć zespołu, który wywołuje kod!

Mój kod:

// deserialize 


using (var target = new System.IO.FileStream(Path, System.IO.FileMode.OpenOrCreate)) 
{ 
    var bin = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 
    var Obj = bin.Deserialize(target); 
    if (Obj != null) 
    { 
     ObjectToStore = (ObjectTypeInMyAssembly)Obj; 
    } 
} 

// serialize 
using (var target = new System.IO.FileStream(Path, System.IO.FileMode.OpenOrCreate)) 
{ 
    var bin = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 
    bin.Serialize(target, ObjectToStore); 
} 
+0

dobrze, jak o pokazanie kodu gdzie wysadza i strukturę kodu serializacji, a także, jeśli możesz .. – MethodMan

+0

Używaj fuslogvw.exe rozwiązywać montaż problemy z rozdzielczością. –

+0

spójrz na to ... http: //msdn.microsoft.com/en-us/library/system.runtime.serialization.formatters.binary.binaryformatter.aspx – MethodMan

Odpowiedz

0

Co widzę w kodzie zarówno z twojej serialize i deserializacji jest wykorzystanie klasy System.IO.Path zamiast rzeczywistej ścieżki do pliku. I zazwyczaj wykonać to w następujący sposób:

static void Main(string[] args) 
    { 
     string filepath = @"C:\FileLocation\"; 
     string filename = "datasaved.bin"; 
     MyClass something = new MyClass(); 

     // serialize 
     using (FileStream strm = File.OpenWrite(Path.Combine(filepath, filename))) 
     { 
      BinaryFormatter ser = new BinaryFormatter(); 
      ser.Serialize(strm, something); 
     } 

     // deserialize 
     using (FileStream strm = File.OpenRead(Path.Combine(filepath, filename))) 
     { 
      BinaryFormatter ser = new BinaryFormatter(); 
      something = ser.Deserialize(strm) as MyClass; 
     } 
    } 

Uwaga dwie rzeczy: robi deserializowania jak zajmie obiekt jest null lub nie oczekiwany typ. Również nie nadużywam używania var.

8

Czy biblioteka DLL znajduje się w tym samym folderze, co plik EXE?
Widzę, że serializujesz/deserializujesz obiekt, który znajduje się w bibliotece DLL ("MyAssembly"). Podczas deserializacji formater określa nazwę typu na podstawie zserializowanych danych i próbuje znaleźć ten typ w złożeniu w głównym folderze wykonywalnym, czyli folderze EXE.
Rozwiązanie - przenieś plik DLL do folderu EXE. Istnieje sposób na spowodowanie, aby formater przeszukał inny zestaw, przechwycił zdarzenie AppDomain.AssemblyResolve i zwrócił bibliotekę DLL. Zobacz MSDN.

+0

Cool. Szukałem rozwiązania i wypróbowałem wiele z nich. Żaden nie działał, ale to. :) Wielkie dzięki – Newbee

5

Użyłem sztuczki, która działała!

sealed class CustomizedBinder : SerializationBinder 
{ 
    public override Type BindToType(string assemblyName, string typeName) 
    { 
     Type returntype = null; 
     string sharedAssemblyName = "SharedAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"; 
     assemblyName = Assembly.GetExecutingAssembly().FullName; 
     typeName = typeName.Replace(sharedAssemblyName, assemblyName); 
     returntype = 
       Type.GetType(String.Format("{0}, {1}", 
       typeName, assemblyName)); 

     return returntype; 
    } 

    public override void BindToName(Type serializedType, out string assemblyName, out string typeName) 
    { 
     base.BindToName(serializedType, out assemblyName, out typeName); 
     assemblyName = "SharedAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"; 
    } 
} 

użyciu spoiwa dla formatujących binarnej tak:

BinaryFormatter bf = new BinaryFormatter(); 
bf.Binder = new CustomizedBinder(); 
+0

To powinna być zaakceptowana odpowiedź. –

2

chciałbym budować na Sean Ed-Man „s answer, co jest dobre, ale nie działa w moim przypadku.

Jeśli możesz utworzyć instancję klasy, ale BinaryFormatter nie może go rozwiązać, może to zadziałać.

W moim przypadku zestaw wywołujący (PluginAssembly dla tego przykładu) jest uruchamiany jako wtyczka z pliku wykonywalnego, w postaci pliku zip. Z jakiegoś powodu mogę bezpośrednio rozwiązać klasę (od NeededAssembly) podczas tworzenia instancji, ale BinaryFormatter nie może jej rozwiązać. NeededAssembly jest oczywiście zawarty jako odniesienie do projektu PluginAssembly, dlatego mogę go utworzyć. Nie wiem, dlaczego BinaryFormatter jest inny.

Niezależnie od tego, jest to, co pracował dla mnie:

public class PluginAssembly 
{ 
    // (class code here) 

    private sealed class CustomizedBinder : SerializationBinder 
    { 
     public override Type BindToType(string assemblyName, string typeName) 
     { 
      Type returntype = null; 
      if (typeName.StartsWith("NeededAssembly.RemoteClient.MessagePayload")) 
      { 
       returntype = typeof(MessagePayload); 
      } 
      else if (typeName.StartsWith("NeededAssembly.RemoteClient.ResultsPayload")) 
      { 
       returntype = typeof(ResultsPayload); 
      } 
      else if (typeName.Equals("System.Collections.Generic.List`1[[NeededAssembly.ShortResult, NeededAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]")) 
      { 
       returntype = typeof(List<ShortResult>); 
      } 
      else 
      { 
       returntype = 
         Type.GetType(String.Format("{0}, {1}", 
         typeName, assemblyName)); 
      } 
      return returntype; 
     } 

     public override void BindToName(Type serializedType, out string assemblyName, out string typeName) 
     { 
      base.BindToName(serializedType, out assemblyName, out typeName); 
      if (serializedType.ToString().Contains("NeededAssembly")) 
      { 
       assemblyName = typeof(MessagePayload).Assembly.FullName; 
      } 
     } 
    } 
} 

Oczywiście, nie zapomnij go używać:

BinaryFormatter bf = new BinaryFormatter(); 
bf.Binder = new CustomizedBinder(); 

Zasadniczo po prostu dostać typeof do potrzebnej klasy, który Prace.

0

Chciałbym sprawdzić, czy odpowiedź Marca Gravell'a here ma zastosowanie ... w skrócie "Jedną opcją byłoby przeniesienie typu do biblioteki DLL, do której odwołują się oba pozostałe projekty - wtedy jest ona zdefiniowana tylko raz i będzie szczęśliwa "

W moim przypadku tymczasowo stworzyłem kopię klasy, którą zamierzałem serializować (w zespole robi serializację) na wczesnym etapie rozwoju, ale zapomniałem o tym podczas deserializacji! Tak więc deserializator nigdy nie miał dostępu do tej samej klasy, która wykonała szeregowanie!

Warto również sprawdzić właściwości projektu zawierającego klasę serializowaną - Sprawdź, czy w swojej nazwie zestawu nie ma literówek. Możesz również spłaszczyć hierarchie przestrzeni nazw, aby sprawdzić, czy to pomaga.

0

Istnieje jeszcze inne rozwiązanie tego problemu, który polega na wyświetleniu folderu zawierającego zestaw w pliku App.config. Można to zrobić poprzez dodanie elementu probing, tak:

<configuration> 
    <runtime> 
     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
     <probing privatePath="bin;bin2\subbin;bin3"/> 
     </assemblyBinding> 
    </runtime> 
</configuration> 
Powiązane problemy