Merge pull request #8625 from RoosterDragon/type-dict-refactor

Refactor TypeDictionary
This commit is contained in:
Pavel Penev
2015-07-05 17:56:09 +03:00

View File

@@ -17,8 +17,8 @@ namespace OpenRA.Primitives
{ {
public class TypeDictionary : IEnumerable public class TypeDictionary : IEnumerable
{ {
Dictionary<Type, object> dataSingular = new Dictionary<Type, object>(); static readonly Func<Type, List<object>> CreateList = type => new List<object>();
Dictionary<Type, List<object>> dataMultiple = new Dictionary<Type, List<object>>(); readonly Dictionary<Type, List<object>> data = new Dictionary<Type, List<object>>();
public void Add(object val) public void Add(object val)
{ {
@@ -32,63 +32,48 @@ namespace OpenRA.Primitives
void InnerAdd(Type t, object val) void InnerAdd(Type t, object val)
{ {
List<object> objs; data.GetOrAdd(t, CreateList).Add(val);
object obj;
if (dataMultiple.TryGetValue(t, out objs))
objs.Add(val);
else if (dataSingular.TryGetValue(t, out obj))
{
dataSingular.Remove(t);
dataMultiple.Add(t, new List<object> { obj, val });
}
else
dataSingular.Add(t, val);
} }
public bool Contains<T>() public bool Contains<T>()
{ {
return dataSingular.ContainsKey(typeof(T)) || dataMultiple.ContainsKey(typeof(T)); return data.ContainsKey(typeof(T));
} }
public T Get<T>() public T Get<T>()
{ {
if (dataMultiple.ContainsKey(typeof(T))) return (T)Get(typeof(T), true);
throw new InvalidOperationException("TypeDictionary contains multiple instance of type `{0}`".F(typeof(T)));
object ret;
if (!dataSingular.TryGetValue(typeof(T), out ret))
throw new InvalidOperationException("TypeDictionary does not contain instance of type `{0}`".F(typeof(T)));
return (T)ret;
} }
public T GetOrDefault<T>() public T GetOrDefault<T>()
{ {
return (T)GetOrDefault(typeof(T)); var result = Get(typeof(T), false);
if (result == null)
return default(T);
return (T)result;
} }
public object GetOrDefault(Type t) object Get(Type t, bool throwsIfMissing)
{ {
if (dataMultiple.ContainsKey(t)) List<object> ret;
throw new InvalidOperationException("TypeDictionary contains multiple instances of type `{0}`".F(t)); if (!data.TryGetValue(t, out ret))
{
object ret; if (throwsIfMissing)
if (!dataSingular.TryGetValue(t, out ret)) throw new InvalidOperationException("TypeDictionary does not contain instance of type `{0}`".F(t));
return null; return null;
return ret; }
if (ret.Count > 1)
throw new InvalidOperationException("TypeDictionary contains multiple instances of type `{0}`".F(t));
return ret[0];
} }
public IEnumerable<T> WithInterface<T>() public IEnumerable<T> WithInterface<T>()
{ {
List<object> objs; List<object> objs;
object obj; if (data.TryGetValue(typeof(T), out objs))
if (dataMultiple.TryGetValue(typeof(T), out objs))
return objs.Cast<T>(); return objs.Cast<T>();
else if (dataSingular.TryGetValue(typeof(T), out obj)) return new T[0];
return new T[] { (T)obj };
else
return new T[0];
} }
public void Remove<T>(T val) public void Remove<T>(T val)
@@ -104,12 +89,11 @@ namespace OpenRA.Primitives
void InnerRemove(Type t, object val) void InnerRemove(Type t, object val)
{ {
List<object> objs; List<object> objs;
object obj; if (!data.TryGetValue(t, out objs))
return;
if (dataMultiple.TryGetValue(t, out objs)) objs.Remove(val);
objs.Remove(val); if (objs.Count == 0)
else if (dataSingular.TryGetValue(t, out obj)) data.Remove(t);
dataSingular.Remove(t);
} }
public IEnumerator GetEnumerator() public IEnumerator GetEnumerator()