仅包含Serializable对象的字典

时间:2011-08-12 13:37:31

标签: c# generics serialization dictionary

我正在寻找一种方法来确保只有可序列化的对象存储在C#中的Dictionary中。

更具体地说,我希望做一些类似的事情:

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

这个问题是我无法存储整数,布尔值或字符串等基本类型。

有没有办法确保我的词典只包含可以序列化的对象?

5 个答案:

答案 0 :(得分:4)

我认为你不能在编译时这样做,但你可以在运行时完成。如果您构建自己的类派生自Dictionary<TKey, TValue>,那么在您的类的构造函数中,您可以检查附加到TValue类型的属性,并确保SerializableAttribute是其中之一,否则抛出异常。

所有标准基元类型(intbool等)都具有此属性。

答案 1 :(得分:2)

要考虑的一件事是,在可序列化的类中使用SerializableAttribute标记,而不是实现接口。来自MSDN

  

任何可能被序列化的类都必须标记为   SerializableAttribute。如果一个类需要控制它的序列化   进程,它可以实现ISerializable接口。

您需要做的是创建自己的实现IDictioanry接口的类,并且每次有人调用add时,使用反射来检查传入的元素是否具有可序列化属性(如果有,则抛出异常)不)。

代码看起来像

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();
        }
    }
    .....
}

答案 2 :(得分: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));
        }
    }
}

答案 3 :(得分:1)

一个答案是创建一个SerializablePrimative包装类。

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

剩下的作为练习留给读者,但基本上你创建一个适配器来制作这些特定类型&#34; fit&#34;你的字典。

*另请参阅:Types Supported by the Data Contract Serializer

**另请参阅:C#: Using Reflection to Instantiate a Generic Class in .Net

答案 4 :(得分: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对象和基元类型。