2013-02-20 22 views
6

このトピックでスレッドの束を見つけましたが、まだ適用されているスレッドが見つかりませんでした。System.Runtime.Serialization.SerializationException:アセンブリMyAssemblyを見つけることができません

基本的に私の.exeは、シリアル化とロードを行う.dll(MyAssembly)ファイルを読み込みます。明らかに、それは非常に上手くシリアル化されます。

しかし、MyAssembly.dllファイル内のファイルをデシリアライズすると、このポストのタイトルのエラーで爆発します。

誰もが考えている?コードを呼び出すアセンブリが見つからないことを私は理解していません!

マイコード:

// 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

さてどのようにすることができます場合にも、それが吹くコードとシリアルコードの構造を示すについて.. – MethodMan

+0

使用Fuslogvw.exeではをアセンブリのトラブルシューティングを行います解決の問題。 –

+0

このを見てみましょう...のhttp://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatters.binary.binaryformatter.aspx – MethodMan

答えて

0

私はあなたのシリアル化およびデシリアライズの両方で、あなたのコード内で参照する代わりに、ファイルへの実際のパスのSystem.IO.Pathクラスを使用することです。

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

注二つのこと:としてデシリアライズを行うと、オブジェクトがnullかどうか期待されるタイプであることを処理する次のように私は通常これを実行します。また、私はvarの使用を悪用しないでください。

8

DLLはEXEと同じフォルダにありますか?
DLL( "MyAssembly")に存在するオブジェクトをシリアル化/逆シリアル化することがあります。逆シリアル化すると、フォーマッタはシリアル化されたデータから型の名前を判断し、このタイプをアセンブリの実行可能なメインフォルダ、つまりEXEフォルダで検索しようとします。
解決策 - DLLをEXEフォルダに移動します。フォーマッタに別のアセンブリを検索させ、イベントAppDomain.AssemblyResolveをキャプチャしてDLLを返す方法があります。 MSDNを参照してください。

+0

クール。解決策を探していて、それらの多くを試しました。しかし、これは働いていません。 :) ありがとうたくさん – Newbee

5

まあ、私は働いたトリックを使用しました!

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

、バイナリフォーマッタのために、このような バインダーを使用します。

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

これは受け入れられた答えでなければなりません。 –

2

を私は良いですSean Ed-Manさんanswer、上に構築したいのですが、私の場合には動作しません。

のクラスをインスタンス化することはできますが、BinaryFormatterでは解決できない場合は、この方法が役立ちます。

私の場合、呼び出しアセンブリ(この例ではPluginAssembly)は、zipファイルの形で実行可能ファイルからプラグインとして実行されています。なんらかの理由で私はインスタンス化するときにクラス(NeededAssembly)を直接解決できますが、BinaryFormatterは解決できません。 NeededAssemblyはもちろん、PluginAssemblyプロジェクトへの参照として含まれているため、インスタンス化することができます。 BinaryFormatterがなぜ違うのか分かりません。

かかわらず、これが私のために働いていたものです:もちろん

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

、それを使用することを忘れないでください:

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

基本的に私は、単に必要なクラスのtypeofを取得し、その働く

0

Marc Gravellの回答hereが適用されるかどうかをチェックします...「1つのオプションは、他のプロジェクトが参照するライブラリdllに型を移動することです - それは一度しか定義されていません。 「

は、私の場合は、一時的に、私は開発の初期段階で(シリアライズを行うアセンブリで)シリアル化するために意図されたクラスのコピーを作成していたが、デシリアライズするとき、それについて忘れてしまいました!したがってデシリアライザは、シリアライズを行ったのと同じクラスにアクセスできませんでした。

また、シリアル化されているクラスを含むプロジェクトのプロパティをチェックアウトする価値があります。 - アセンブリ名のタイプミスを確認してください。名前空間の階層化を平坦化して、それが役立つかどうかを調べることもできます。

0

この問題のもう1つの解決方法は、App.configでアセンブリを含むフォルダを一覧表示することです。あなたはこのように、probing要素を追加することによって、この操作を行います。

<configuration> 
    <runtime> 
     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
     <probing privatePath="bin;bin2\subbin;bin3"/> 
     </assemblyBinding> 
    </runtime> 
</configuration> 
関連する問題