2011-08-12 15 views
6

シリアライズ可能なオブジェクトだけがC#でディクショナリに格納されるようにする方法を模索しています。シリアライズ可能なオブジェクトのみを含むディクショナリ

具体的には、私はこれに似た何かを探しています:

Dictionary<String, ISerializable> serialDict = new Dictionary<String, ISerializable>(); 

これに伴う問題は、私は、整数、ブール値、または文字列などのプリミティブ型を格納することはできませんということです。

ディクショナリにはシリアル化できるオブジェクトのみが含まれていることを確認する方法はありますか?

答えて

4

コンパイル時にこれを行うことはできませんが、実行時に行うことができます。 Dictionary<TKey, TValue>から派生した独自のクラスを作成する場合は、クラスのコンストラクタでTValueタイプにアタッチされている属性をチェックし、SerializableAttributeがその1つであることを確認してください。

すべての標準プリミティブタイプ(int,boolなど)はこの属性を持っています。

+0

C#: Using Reflection to Instantiate a Generic Class in .Netは、洞察力をありがとう、これはより理にかなっています。私はコンパイル時の解決策を期待していましたが、これはうまくいくでしょう。 – LamdaComplex

0

辞書のラッピングはどうですか?

class SomeClass { 

    Dictionary<string,object> d; 
    // add ISerializable 
    public void Add(string key, ISerializable value) { 
     d[key] = value; 
    } 
    // add primitive types 
    public void Add(string key, bool value) { 
     d[key] = value; 
    } 
    public void Add(string key, int value) { 
     d[key] = value; 
    } 
    // etc ... 
} 

このようにして、ISerializableオブジェクトとプリミティブ型だけを追加できます。考慮すべき

+1

MSDNのドキュメントでは、シリアル化プロセスを制御したい場合、オブジェクトはISerializableインターフェイスを実装する必要があります。したがって、すべてのシリアライズ可能オブジェクトがこのインタフェースを実装するわけではありません – R0MANARMY

1
[Serializable] 
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue> 
{ 
    static SerializableDictionary() 
    { 
     AssertSerializable(typeof(TKey)); 
     AssertSerializable(typeof(TValue)); 
    } 

    static void AssertSerializable(Type t) 
    { 
     if (!t.IsSerializable) 
     { 
      throw new NotSupportedException(string.Format(
       "{0} is not serializable", t.Name)); 
     } 
    } 
} 
+1

このディクショナリでint、boolean、およびstringを格納したい場合、どのタイプをTValueとして選択する必要がありますか? –

+0

@David良い点、+1。それはサポートされていません。しかし、質問者は、質問者がこれらのタイプのうちの1つを保存したいのではなく、それらの組み合わせではないかのように質問を読んでいます。 –

2

ことの一つは、インターフェイスを実装するとは対照的に、直列化可能なクラスにSerializableAttributeでタグ付けされていることです。 MSDNから:

SerializableAttributeでマークする必要がありますシリアライズされる可能性があります任意のクラス。クラスがシリアライズ プロセスを制御する必要がある場合は、ISerializableインターフェイスを実装できます。何をする必要があるだろうが使用反射が渡された要素は、直列化可能属性を持っているかどうかを確認(そして、それはdoesnの場合に例外をスローするように、IDictioanryインターフェースと、誰かが追加呼び出すたびに実装する独自のクラスを作るです

't)。

コードは、1つの答えがSerializablePrimativeラッパークラスを作成することです

class MyDictionary<TKey, TValue> : IDictionary<TKey, TValue> 
{ 
    private Dictionary<TKey, TValue> d; 

    public void Add(TKey key, TValue value) 
    { 
     if(value.GetType().IsSerializable) 
     { 
      d.Add(key, value); 
     } 
     else 
     { 
      throw new ArgumentException(); 
     } 
    } 
    ..... 
} 
+0

私はこの解決策も好きです。私のプロジェクトに必要なことだけです。ありがとうございました。 – LamdaComplex

1

ようになります。

class SerializablePrimative<T> : ISerializable { 
    private T val = default(); 

    private SerializablePrimative(T newVal){ 
     val = newVal; 
    } 

    public static boolean IsSupported(Object o){ 
     if (o == null){ 
      return false; 
     }else{ 
      return IsSupported(o.GetType()); 
     } 
    } 

    public static boolean IsSupported(Type t){ 
     if (// you want to support* ...) 
     { 
      return true; 
     } 
     else 
     { 
     return false; 
     } 
    } 

    public static SerializablePrimative GetSerializable(Object o){ 
     if (IsSupported(o)){ 
      return //Intstatiate via Reflection ** 
     }else { 
      return null; 
     } 
    } 
} 

残りは読者への課題として残しますが、基本的にあなたは、これらの特定の種類の辞書を「フィット」にするアダプタを作成しています。

*参照:Types Supported by the Data Contract Serializer

は**関連項目:

+0

これは、シリアライズ可能なクラス(プリミティブを含む)が既に適切な属性でタグ付けされていることを考えると、過剰なようです。 – R0MANARMY

関連する問題