C # Typedef, который сохраняет атрибуты - PullRequest
6 голосов
/ 04 февраля 2011

Проблема: у меня есть Dictionary<String, String>, для которого мне нужен псевдоним, но мне также нужно его сериализовать / десериализовать.

Решения, которые я пробовал:

class Foo : Dictionary<String, String> { }

но это работает, потому что мне пришлось бы создавать конструктор десериализации, и это было бы немного глупо, когда словарь уже можно десериализовать.

Я тоже пробовал

using Foo = System.Collections.Generic.Dictionary<String, String>;

но мне нужно, чтобы это работало в более чем одном файле, и если добавить эту строку во все файлы, которые в ней нуждаются, я буду удалять половину точки typedefs (то есть, если мне нужно изменить тип, может сделать это легко)

Что я могу с этим поделать?

Ответы [ 2 ]

6 голосов
/ 04 февраля 2011

При использовании псевдоним атрибуты подхода сохраняются, но вы заявляете, что слишком много накладных расходов (для каждого файла и т. Д.).

Атрибуты уровня типа являются общими для сохранения - но это зависит от атрибута - для [Serializable] обратите внимание, что оно имеет:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct
| AttributeTargets.Enum | AttributeTargets.Delegate, Inherited = false)]

значение Inherited = false является значительным - то есть оно не наследуется.

Лично я, вероятно, сосредоточился бы на том, чтобы заставить сериализацию ctor / callback'ов работать в первом примере - я сомневаюсь, что это потребовало бы гораздо больше усилий. Следующее выглядит хорошо:

[Serializable]
public class Foo: Dictionary<string, string> {
    public Foo() : base() { }
    public Foo(SerializationInfo info, StreamingContext context) : base(info, context) { }
    public Foo(int capacity) : base(capacity) { }
    public Foo(IEqualityComparer<string> comparer): base(comparer) {}
    public Foo(IDictionary<string,string> dictionary) : base(dictionary) { }
    public Foo(int capacity, IEqualityComparer<string> comparer) : base(capacity, comparer) { }
    public Foo(IDictionary<string, string> dictionary, IEqualityComparer<string> comparer) : base(dictionary, comparer) { }
}

Однако есть альтернатива через инкапсуляцию:

[Serializable]
public class Foo : IDictionary<string,string>
{
    private readonly Dictionary<string, string> inner = new Dictionary<string, string>();

    public void Add(string key, string value)
    {
        inner.Add(key, value);
    }

    public bool ContainsKey(string key)
    {
        return inner.ContainsKey(key);
    }

    public ICollection<string> Keys
    {
        get { return inner.Keys; }
    }

    public bool Remove(string key)
    {
        return inner.Remove(key);
    }

    public bool TryGetValue(string key, out string value)
    {
        return inner.TryGetValue(key, out value);
    }

    public ICollection<string> Values
    {
        get { return inner.Values; }
    }

    public string this[string key]
    {
        get
        {
            return inner[key];
        }
        set
        {
            inner[key] = value;
        }
    }

    void  ICollection<KeyValuePair<string, string>>.Add(KeyValuePair<string, string> item)
    {
        ((IDictionary<string,string>)inner).Add(item);
    }

    public void Clear()
    {
        inner.Clear();
    }

    bool ICollection<KeyValuePair<string, string>>.Contains(KeyValuePair<string, string> item)
    {
        return ((IDictionary<string, string>)inner).Contains(item);
    }

    void  ICollection<KeyValuePair<string, string>>.CopyTo(KeyValuePair<string, string>[] array, int arrayIndex)
    {
        ((IDictionary<string, string>)inner).CopyTo(array, arrayIndex);
    }

    public int Count
    {
        get { return inner.Count; }
    }

    bool  ICollection<KeyValuePair<string, string>>.IsReadOnly
    {
        get { return ((IDictionary<string, string>)inner).IsReadOnly; }
    }

    bool ICollection<KeyValuePair<string, string>>.Remove(KeyValuePair<string, string> item)
    {
        return ((IDictionary<string, string>)inner).Remove(item);
    }

    public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
    {
        return inner.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return inner.GetEnumerator();
    }
}
1 голос
/ 04 февраля 2011

Ммм "это было бы немного глупо, когда словарь уже можно десериализовать".Я бы не сказал, что глупо вызывать базовый ctor в (почти) любом случае + это 1 минутное усилие, поэтому я бы сказал, сделайте это ...

[Serializable]
public class Foo : Dictionary<string, string>
{
    public Foo()
        : base()
    {
    }
    public Foo(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
    }   

}

или

[Serializable]
public class Foo<TKey,TValue> : Dictionary<TKey,TValue>
{
    public Foo()
        : base()
    {
    }
    public Foo(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
    }   

}
...