Словарь, содержащий только сериализуемые объекты - PullRequest
6 голосов
/ 12 августа 2011

Я ищу способ гарантировать, что только сериализуемые объекты хранятся в словаре в C #.

Чтобы быть более конкретным, я собираюсь сделать что-то похожее на это:

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

Проблема в том, что я не могу хранить примитивные типы, такие как целые числа, логические значения или строки.

Есть ли способ убедиться, что мой словарь содержит только объекты, которые можно сериализовать?

Ответы [ 5 ]

4 голосов
/ 12 августа 2011

Я не думаю, что вы можете сделать это во время компиляции, но вы можете сделать это во время выполнения. Если вы создаете свой собственный класс, производный от Dictionary<TKey, TValue>, то в конструкторе вашего класса вы можете проверить атрибуты, связанные с типом TValue, и убедиться, что SerializableAttribute является одним из них, иначе выведите исключение.

Все стандартные типы примитивов (int, bool и т. Д.) Имеют этот атрибут.

2 голосов
/ 12 августа 2011

Следует учитывать, что в сериализуемых классах теги 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();
        }
    }
    .....
}
1 голос
/ 12 августа 2011

Одним из ответов будет создание класса-обертки SerializablePrirative.

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

Остальное оставлено в качестве упражнения для читателя, но в основном вы создаете адаптер, чтобы эти определенные типы "подходили" вашему словарю..

* См. Также: Типы, поддерживаемые сериализатором контракта данных

** См. Также: C #: использование отражения для создания общего класса в .Net

1 голос
/ 12 августа 2011
[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));
        }
    }
}
0 голосов
/ 12 августа 2011

Как насчет упаковки вашего словаря?

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 и типы примитивов.

...