I need a container that works like a ditionary but where the type of data (TValue
) change from one key to the other.
I also need to iterate trough it.
I need a container that works like a ditionary but where the type of data (TValue
) change from one key to the other.
I also need to iterate trough it.
For the heterogeneous and type-safe dictionary part
Wilka response is a good start.
The trick is to put the type in the key.
/// <summary>
/// Base class for all dictionary key.
///
/// <remarks>The key name is REALLY usefull for debug purpose.</remarks>
/// </summary>
abstract class HeterogeneousDictionaryKeyBase
{
readonly string _name;
protected HeterogeneousDictionaryKeyBase(string name)
{
_name = name;
}
public override string ToString()
{
return _name;
}
}
sealed class HeterogeneousDictionaryKey<TValue> : HeterogeneousDictionaryKeyBase
{
public HeterogeneousDictionaryKey(string name)
: base(name)
{
}
}
So calls to dictionary will have a generic value type:
/// <summary>
/// <remarks>The [] operator can not be generic, so we implement it has a getter and a setter</remarks>
/// </summary>
class HeterogeneousDictionary
{
private readonly Dictionary<HeterogeneousDictionaryKeyBase, object> _dictionary = new Dictionary<HeterogeneousDictionaryKeyBase, object>();
public void Add<TValue>(HeterogeneousDictionaryKey<TValue> key, TValue value)
{
_dictionary.Add(key, value);
}
public TValue Get<TValue>(HeterogeneousDictionaryKey<TValue> key)
{
return (TValue)_dictionary[key];
}
public void Set<TValue>(HeterogeneousDictionaryKey<TValue> key, TValue value)
{
_dictionary[key] = value;
}
public bool TryGetValue<TValue>(HeterogeneousDictionaryKey<TValue> key, out TValue value)
{
object result;
if (_dictionary.TryGetValue(key, out result) && result is TValue)
{
value = (TValue)result;
return true;
}
value = default(TValue);
return false;
}
}
The usage is simple:
var dictionary = new HeterogeneousDictionary();
var keyName = new HeterogeneousDictionaryKey<string>("keyName");
var keyAge = new HeterogeneousDictionaryKey<int>("keyAge");
dictionary.Set(keyName, "Orace");
dictionary.Set(keyAge, 8);
...
var name = dictionary.Get(keyName);
var age = dictionary.Get(keyAge);
For the iteration part
A visitor pattern against the dictionary keys will do the trick.
First the visitor interface:
interface IHeterogeneousDictionaryKeyVisitor
{
void Visit<TValue>(HeterogeneousDictionaryKey<TValue> key);
}
Then we made the HeterogeneousDictionaryKey
cooperate:
abstract class HeterogeneousDictionaryKeyBase
{
...
public abstract void Accept(IHeterogeneousDictionaryKeyVisitor visitor);
...
}
sealed class HeterogeneousDictionaryKey<TValue> : HeterogeneousDictionaryKeyBase
{
...
public override void Accept(IHeterogeneousDictionaryKeyVisitor visitor)
{
visitor.Visit(this);
}
}
Now we can expose the HeterogeneousDictionary
keys:
class HeterogeneousDictionary
{
...
public Dictionary<HeterogeneousDictionaryKeyBase, object>.KeyCollection Keys
{
get { return _dictionary.Keys; }
}
...
}
And that it all.
Here an example of usage to safely copy a dictionary to an other
class DictionaryCopier : IHeterogeneousDictionaryKeyVisitor
{
readonly HeterogeneousDictionary _source;
readonly HeterogeneousDictionary _destination;
public DictionaryCopier(HeterogeneousDictionary source, HeterogeneousDictionary destination)
{
_source = source;
_destination = destination;
}
public void PerformCopy()
{
foreach (var key in _source.Keys)
{
// See you soon.
key.Accept(this);
}
}
/// <summary>
/// We fall back here with a typed key.
/// </summary>
public void Visit<TValue>(HeterogeneousDictionaryKey<TValue> key)
{
// Here the value is typed.
var value = _source.Get(key);
_destination.Add(key, value);
}
}
© 2022 - 2024 — McMap. All rights reserved.