C# cast Dictionary to Dictionary (Involving Reflection)

前端 未结 8 1044
无人及你
无人及你 2021-01-04 10:04

Is it possible to cast a Dictionary to a consistent intermediate generic type? So I would be able to cast <

8条回答
  •  情歌与酒
    2021-01-04 10:31

    I had the same situation and created a WrapperDictionary class and a cast extension method. Found it helpful if you also want to make operations with it like remove a item.

    Example:

            const string TestKey1 = "Key";
            const string TestValue1 = "Value";
            var dict = new Dictionary();
            dict.Add(TestKey1, TestValue1);
    
            var wrapper = dict.CastDictionary();
    
            wrapper.Remove(TestKey1);
    

    Code:

    public class DictionaryWrapper : IDictionary
    {
        #region types
    
        private class EnumeratorWrapper : IEnumerator>
        {
            private readonly IEnumerator> _enumerator;
            private readonly DictionaryWrapper _dictionaryWrapper;
    
            public EnumeratorWrapper(IEnumerator> enumerator, DictionaryWrapper dictionaryWrapper)
            {
                _enumerator = enumerator;
                _dictionaryWrapper = dictionaryWrapper;
            }
    
            public void Dispose()
            {
                _enumerator.Dispose();
            }
    
            public bool MoveNext()
            {
                return _enumerator.MoveNext();
            }
    
            public void Reset()
            {
                _enumerator.Reset();
            }
    
            public KeyValuePair Current => _dictionaryWrapper._kvpSourceToTargetFunc(_enumerator.Current);
    
            object IEnumerator.Current => Current;
        }
    
        #endregion
    
        #region fields
    
        private readonly IDictionary _dictionary;
        private readonly Func _keySourceToTargetFunc;
        private readonly Func _keyTargetToSourceFunc;
        private readonly Func _valueSourceToTargetFunc;
        private readonly Func _valueTargetToSourceFunc;
        private readonly Func, KeyValuePair> _kvpSourceToTargetFunc;
        private readonly Func, KeyValuePair> _kvpTargetToSourceFunc;
    
        #endregion
    
        #region Construction
    
        public DictionaryWrapper(
            IDictionary dict, 
            Func keySourceToTargetFunc = null,
            Func keyTargetToSourceFunc = null, 
            Func valueSourceToTargetFunc = null, 
            Func valueTargetToSourceFunc = null)
        {
            _dictionary = dict;
            _keySourceToTargetFunc = keySourceToTargetFunc ?? (i => (TKeyTarget) (object) i);
            _keyTargetToSourceFunc = keyTargetToSourceFunc ?? (i => (TKeySource) (object) i);
            _valueSourceToTargetFunc = valueSourceToTargetFunc ?? (i => (TValueTarget) (object) i);
            _valueTargetToSourceFunc = valueTargetToSourceFunc ?? (i => (TValueSource) (object) i);
            _kvpSourceToTargetFunc = 
                kvp => new KeyValuePair(_keySourceToTargetFunc(kvp.Key), _valueSourceToTargetFunc(kvp.Value));
            _kvpTargetToSourceFunc = 
                kvp => new KeyValuePair(_keyTargetToSourceFunc(kvp.Key), _valueTargetToSourceFunc(kvp.Value));
        }
    
        #endregion
    
        #region Interface Members
    
        public IEnumerator> GetEnumerator()
        {
            return new EnumeratorWrapper(_dictionary.GetEnumerator(), this);
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    
        public void Add(KeyValuePair item)
        {
            _dictionary.Add(_kvpTargetToSourceFunc(item));
        }
    
        public void Clear()
        {
            _dictionary.Clear();
        }
    
        public bool Contains(KeyValuePair item)
        {
            return _dictionary.Contains(_kvpTargetToSourceFunc(item));
        }
    
        public void CopyTo(KeyValuePair[] array, int arrayIndex)
        {
            throw new NotImplementedException();
        }
    
        public bool Remove(KeyValuePair item)
        {
            return _dictionary.Remove(_kvpTargetToSourceFunc(item));
        }
    
        public int Count => _dictionary.Count;
        public bool IsReadOnly => _dictionary.IsReadOnly;
        public bool ContainsKey(TKeyTarget key)
        {
            return _dictionary.ContainsKey(_keyTargetToSourceFunc(key));
        }
    
        public void Add(TKeyTarget key, TValueTarget value)
        {
            _dictionary.Add(_keyTargetToSourceFunc(key), _valueTargetToSourceFunc(value));
        }
    
        public bool Remove(TKeyTarget key)
        {
            return _dictionary.Remove(_keyTargetToSourceFunc(key));
        }
    
        public bool TryGetValue(TKeyTarget key, out TValueTarget value)
        {
            var success = _dictionary.TryGetValue(_keyTargetToSourceFunc(key), out TValueSource result);
            value = success ? _valueSourceToTargetFunc(result) : default;
            return success;
        }
    
        public TValueTarget this[TKeyTarget key]
        {
            get => _valueSourceToTargetFunc(_dictionary[_keyTargetToSourceFunc(key)]);
            set => _dictionary[_keyTargetToSourceFunc(key)] = _valueTargetToSourceFunc(value);
        }
    
        public ICollection Keys => _dictionary.Keys.Select(k => _keySourceToTargetFunc(k)).ToList();
        public ICollection Values => _dictionary.Values.Select(v => _valueSourceToTargetFunc(v)).ToList();
    
        #endregion
    }
    
    public static class DictionaryWrapperExtensions
    {
        public static IDictionary CastDictionary(this IDictionary dictionary)
        {
            return new DictionaryWrapper(dictionary);
        }
    }
    

提交回复
热议问题