2017-03-05 7 views
0

ListManager型のオブジェクトを逆シリアル化しようとしていますが、試行時にキャストエラーが発生します。私は間違って何をしているのかわからない。ジェネリックをバイナリ逆シリアル化

私は

b.Serialize(fileStream, obj); 

に送信する。しかし、私はバックキャストエラーを取得するのListManagerのインスタンスにファイルをデシリアライズしようとしたときでわずか罰金オブジェクトをシリアル化。クラスは "AnimalManager"と呼ばれ、ListManagerから継承されます。このクラスには、Animal型のオブジェクトのリストが含まれています。どのようにListmanagerではなく、動物にキャストしたいのですか?

タイプ「AnimalManager」のオブジェクトは、タイプ「Animal」のオブジェクトに変換できません。

をForm1から呼び出す
public static T OpenBin<T>(string filePath) 
{ 
    FileStream fileStream = null; 
    object obj; 

    try 
    { 
     if (!File.Exists(filePath)) throw new FileNotFoundException("The file" + " was not found. ", filePath); 

     fileStream = new FileStream(filePath, FileMode.Open); 

     var b = new BinaryFormatter(); 

     obj = b.Deserialize(fileStream); 
    } 

    finally 
    { 
     fileStream?.Close(); 
    } 

    return (T)obj; 
} 

[Serializable] 
public class ListManager<T> : IListManager<T> 
{ 
    private List<T> _mList; 

    public ListManager() 
    { 
     _mList = new List<T>(); 
    } 
} 

[Serializable] 
public class AnimalManager : ListManager<Animal> 
{ 
} 

private void button4_Click(object sender, EventArgs e) 
    { 
     var filepath = "test.bin"; 

     if (manager.BinaryDeSerialize(filepath)) 
     { 
      MessageBox.Show("hhohjo"); 
     } 
    } 

はListManagerのインスタンス(AnimalManager)

public bool BinaryDeSerialize(string fileName) 
    { 
     var test = BinSerializerUtility.OpenBin<T>(fileName); 

     return true; 
    } 
+2

あなたはOpenBinのあなたの通話だけでなく、あなたのシリアライズを表示することができますか? –

+1

[ask]を読んで[mcve]を入力してください。シリアライズしたのと同じ型にデシリアライズするのではなく、 'T 'をどこかに混乱させていますが、これをコードから解析することはできません。 – CodeCaster

答えて

2

に行くあなたの問題は、あなたがOpenBin呼び出している方法です。 OpenBinに渡すジェネリックは、あなたがListManagerに保存しているタイプです。これは、シリアライゼーションが動作している間に、非直列化がオブジェクトをT型にキャストしようとしていることを意味します。これは、AnimalManagerの場合はAnimalです。解決策は、OpenBinを非ジェネリックにすることですが、それを抽象化してAnimalManagerに実装して、TでなくAnimalManagerにキャストすることです。

もっと良い解決策は、OpenBinに第2の汎用変数を提供することです。 Tは、コンテナの要素によって使用されているので、そのような静的な機能のために別のものを指定:

var test = BinSerializerUtility.OpenBin<AnimalManager>(fileName); 

public static E OpenBin<E>(string filePath) 

をあなたはかかわらず、関数を呼び出すときに同じように、タイプを指定する必要があります

これらの方法のいずれかの問題は、サブクラスに型を指定する必要があることです。

これは、リフレクションを使用して、親クラスでそれを行うための方法を提供することができる:

How do I use reflection to call a generic method?

+0

返信いただきありがとうございます! –

+0

しかし、一般的な脱塩方法はありませんか?私はこれをAnimalManagerだけでなく、どのようなタイプの "ListManager"でも実装したいと思いますか? –

+0

そうですが、第2の汎用変数を指定する方が良いでしょう。私は私の答えを更新する –