perf in TypeDictionary
This commit is contained in:
@@ -8,49 +8,73 @@ namespace OpenRa.FileFormats
|
|||||||
{
|
{
|
||||||
public class TypeDictionary
|
public class TypeDictionary
|
||||||
{
|
{
|
||||||
Cache<Type, List<object>> innerInherit = new Cache<Type, List<object>>( _ => new List<object>() );
|
Dictionary<Type, object> dataSingular = new Dictionary<Type, object>();
|
||||||
|
Dictionary<Type, List<object>> dataMultiple = new Dictionary<Type, List<object>>();
|
||||||
|
|
||||||
public void Add( object val )
|
public void Add( object val )
|
||||||
{
|
{
|
||||||
var t = val.GetType();
|
var t = val.GetType();
|
||||||
|
|
||||||
foreach( var i in t.GetInterfaces() )
|
foreach( var i in t.GetInterfaces() )
|
||||||
innerInherit[ i ].Add( val );
|
InnerAdd( i, val );
|
||||||
foreach( var tt in t.BaseTypes() )
|
foreach( var tt in t.BaseTypes() )
|
||||||
innerInherit[ tt ].Add( val );
|
InnerAdd( tt, val );
|
||||||
|
}
|
||||||
|
|
||||||
|
void InnerAdd( Type t, object val )
|
||||||
|
{
|
||||||
|
List<object> objs;
|
||||||
|
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 innerInherit[ typeof( T ) ].Count != 0;
|
return dataSingular.ContainsKey( typeof( T ) ) || dataMultiple.ContainsKey( typeof( T ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public T Get<T>()
|
public T Get<T>()
|
||||||
{
|
{
|
||||||
var l = innerInherit[typeof(T)];
|
if( dataMultiple.ContainsKey( typeof( T ) ) )
|
||||||
if (l.Count == 1)
|
throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
|
||||||
return (T)l[0];
|
|
||||||
else if (l.Count == 0)
|
object ret;
|
||||||
|
if( !dataSingular.TryGetValue( typeof( T ), out ret ) )
|
||||||
throw new InvalidOperationException(string.Format("TypeDictionary does not contain instance of type `{0}`", typeof(T)));
|
throw new InvalidOperationException(string.Format("TypeDictionary does not contain instance of type `{0}`", typeof(T)));
|
||||||
else
|
return (T)ret;
|
||||||
throw new InvalidOperationException(string.Format("TypeDictionary contains multiple instance of type `{0}`", typeof(T)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public T GetOrDefault<T>()
|
public T GetOrDefault<T>()
|
||||||
{
|
{
|
||||||
var l = innerInherit[ typeof( T ) ];
|
if( dataMultiple.ContainsKey( typeof( T ) ) )
|
||||||
if( l.Count == 1 )
|
|
||||||
return (T)l[ 0 ];
|
|
||||||
else if( l.Count == 0 )
|
|
||||||
return default( T );
|
|
||||||
else
|
|
||||||
throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
|
throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
|
||||||
|
|
||||||
|
object ret;
|
||||||
|
if( !dataSingular.TryGetValue( typeof( T ), out ret ) )
|
||||||
|
return default( T );
|
||||||
|
return (T)ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<T> WithInterface<T>()
|
public IEnumerable<T> WithInterface<T>()
|
||||||
{
|
{
|
||||||
foreach( var i in innerInherit[ typeof( T ) ] )
|
List<object> objs;
|
||||||
yield return (T)i;
|
object obj;
|
||||||
|
|
||||||
|
if( dataMultiple.TryGetValue( typeof( T ), out objs ) )
|
||||||
|
return objs.Cast<T>();
|
||||||
|
else if( dataSingular.TryGetValue( typeof( T ), out obj ) )
|
||||||
|
return new T[] { (T)obj };
|
||||||
|
else
|
||||||
|
return new T[ 0 ];
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerator<object> GetEnumerator()
|
public IEnumerator<object> GetEnumerator()
|
||||||
|
|||||||
Reference in New Issue
Block a user