Browse Source

Grid visualizer:

- refactored value providers
- values are obtained from debugger only for displayed columns
- scrolls to top when new variable inspected

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4577 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Martin Koníček 17 years ago
parent
commit
4daa29a0eb
  1. 3
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj
  2. 39
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs
  3. 2
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/LazyListView.cs
  4. 79
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ObjectValue.cs
  5. 27
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/EnumerableValuesProvider.cs
  6. 50
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/GridValuesProvider.cs
  7. 26
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs
  8. 3
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/VirtualizingIEnumerable.cs
  9. 2
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/PresentationBindings/GridViewColumnHider.cs
  10. 41
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/PresentationBindings/ScrollUtils.cs
  11. 48
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/IEnumerableExtensions.cs
  12. 21
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/Lookup.cs

3
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj

@ -145,9 +145,12 @@
<Compile Include="Src\Visualizers\Graph\TreeModel\NonPublicMembersNode.cs" /> <Compile Include="Src\Visualizers\Graph\TreeModel\NonPublicMembersNode.cs" />
<Compile Include="Src\Visualizers\Graph\TreeModel\PropertyNode.cs" /> <Compile Include="Src\Visualizers\Graph\TreeModel\PropertyNode.cs" />
<Compile Include="Src\Visualizers\GridVisualizer\SelectedProperties.cs" /> <Compile Include="Src\Visualizers\GridVisualizer\SelectedProperties.cs" />
<Compile Include="Src\Visualizers\GridVisualizer\ValueProviders\GridValuesProvider.cs" />
<Compile Include="Src\Visualizers\PresentationBindings\GridViewColumnHider.cs" /> <Compile Include="Src\Visualizers\PresentationBindings\GridViewColumnHider.cs" />
<Compile Include="Src\Visualizers\PresentationBindings\ScrollUtils.cs" />
<Compile Include="Src\Visualizers\PresentationBindings\TooltipVisibilityConverter.cs" /> <Compile Include="Src\Visualizers\PresentationBindings\TooltipVisibilityConverter.cs" />
<Compile Include="Src\Visualizers\Utils\AtomicType.cs" /> <Compile Include="Src\Visualizers\Utils\AtomicType.cs" />
<Compile Include="Src\Visualizers\Utils\IEnumerableExtensions.cs" />
<Compile Include="Src\Visualizers\Utils\ITreeNode.cs" /> <Compile Include="Src\Visualizers\Utils\ITreeNode.cs" />
<Compile Include="Src\Visualizers\Utils\LinqUtils.cs" /> <Compile Include="Src\Visualizers\Utils\LinqUtils.cs" />
<Compile Include="Src\Visualizers\Utils\ListHelper.cs" /> <Compile Include="Src\Visualizers\Utils\ListHelper.cs" />

39
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs

@ -39,7 +39,11 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
private void btnInspect_Click(object sender, RoutedEventArgs e) private void btnInspect_Click(object sender, RoutedEventArgs e)
{ {
// clear ListView
listView.ItemsSource = null; listView.ItemsSource = null;
ScrollViewer listViewScroller = listView.GetScrollViewer();
if (listViewScroller != null)
listViewScroller.ScrollToVerticalOffset(0);
this.debuggerService = DebuggerService.CurrentDebugger as WindowsDebugger; this.debuggerService = DebuggerService.CurrentDebugger as WindowsDebugger;
if (debuggerService == null) if (debuggerService == null)
@ -56,35 +60,40 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
} }
if (val != null && !val.IsNull) if (val != null && !val.IsNull)
{ {
DebugType iListType, listItemType; GridValuesProvider gridValuesProvider;
IList<MemberInfo> itemTypeMembers = null;
// Value is IList?
DebugType iListType, listItemType;
if (val.Type.ResolveIListImplementation(out iListType, out listItemType)) if (val.Type.ResolveIListImplementation(out iListType, out listItemType))
{ {
var valuesProvider = new ListValuesProvider(val.ExpressionTree, iListType, listItemType); var listValuesProvider = new ListValuesProvider(val.ExpressionTree, iListType, listItemType);
var virtCollection = new VirtualizingCollection<ObjectValue>(valuesProvider); var virtCollection = new VirtualizingCollection<ObjectValue>(listValuesProvider);
itemTypeMembers = valuesProvider.GetItemTypeMembers();
this.listView.ItemsSource = virtCollection; this.listView.ItemsSource = virtCollection;
gridValuesProvider = listValuesProvider;
} }
else else
{ {
// Value is IEnumerable?
DebugType iEnumerableType, itemType; DebugType iEnumerableType, itemType;
if (val.Type.ResolveIEnumerableImplementation(out iEnumerableType, out itemType)) if (val.Type.ResolveIEnumerableImplementation(out iEnumerableType, out itemType))
{ {
var lazyListViewWrapper = new LazyListView<ObjectValue>(this.listView); var lazyListViewWrapper = new LazyListView<ObjectValue>(this.listView);
var iEnumerableValuesProvider = new EnumerableValuesProvider(val.ExpressionTree, iEnumerableType, itemType); var enumerableValuesProvider = new EnumerableValuesProvider(val.ExpressionTree, iEnumerableType, itemType);
lazyListViewWrapper.ItemsSource = new VirtualizingIEnumerable<ObjectValue>(enumerableValuesProvider.ItemsSource);
itemTypeMembers = iEnumerableValuesProvider.GetItemTypeMembers(); gridValuesProvider = enumerableValuesProvider;
}
lazyListViewWrapper.ItemsSource = new VirtualizingIEnumerable<ObjectValue>(iEnumerableValuesProvider.ItemsSource); else
{
// Value cannot be displayed in GridVisualizer
return;
} }
} }
IList<MemberInfo> itemTypeMembers = gridValuesProvider.GetItemTypeMembers();
// create ListView columns
createGridViewColumns((GridView)this.listView.View, itemTypeMembers); createGridViewColumns((GridView)this.listView.View, itemTypeMembers);
this.columnHider = new GridViewColumnHider((GridView)this.listView.View); this.columnHider = new GridViewColumnHider((GridView)this.listView.View);
// fill column-choosing ComboBox
this.selectedProperties = initializeSelectedPropertiesWithEvents(itemTypeMembers); this.selectedProperties = initializeSelectedPropertiesWithEvents(itemTypeMembers);
cmbColumns.ItemsSource = this.selectedProperties; cmbColumns.ItemsSource = this.selectedProperties;
} }
@ -119,11 +128,11 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
var columnName = propertySeleted.Name; var columnName = propertySeleted.Name;
if (propertySeleted.IsSelected) if (propertySeleted.IsSelected)
{ {
columnHider.ShowColumn(columnName); this.columnHider.ShowColumn(columnName);
} }
else else
{ {
columnHider.HideColumn(columnName); this.columnHider.HideColumn(columnName);
} }
} }
} }

2
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/LazyListView.cs

@ -37,7 +37,7 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
set set
{ {
this.itemsSource = value; this.itemsSource = value;
this.itemsSource.RequestNextItems(14); this.itemsSource.RequestNextItems(25);
this.listView.ItemsSource = value; this.listView.ItemsSource = value;
} }
} }

79
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ObjectValue.cs

@ -18,40 +18,77 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
/// </summary> /// </summary>
public class ObjectValue public class ObjectValue
{ {
// couldn't be properties loaded lazily? - when listview databinding asks for key, we could ask fetch the value from debugger // Used to be able to expand items of IEnumerable
// Now we rely on PermanentReference to be able to get member values on demand. With IList, PermanentReference can be replaced by Expression
public Value PermanentReference { get; private set; }
private Dictionary<string, ObjectProperty> properties = new Dictionary<string, ObjectProperty>(); private Dictionary<string, ObjectProperty> properties = new Dictionary<string, ObjectProperty>();
/// <summary> Used to quickly find MemberInfo by member name - DebugType.GetMember(name) uses a loop to search members </summary>
private Dictionary<string, MemberInfo> memberFromNameMap;
internal ObjectValue(Dictionary<string, MemberInfo> memberFromNameMap)
{
this.memberFromNameMap = memberFromNameMap;
}
/// <summary> /// <summary>
/// Returns property with given name. /// Returns property with given name.
/// </summary> /// </summary>
public ObjectProperty this[string key] public ObjectProperty this[string key]
{ {
get { return properties.GetValue(key); } get
set { properties[key] = value; } {
ObjectProperty property;
// has property with name 'propertyName' already been evaluated?
if(!this.properties.TryGetValue(key, out property))
{
if (this.PermanentReference == null) {
throw new DebuggerVisualizerException("Cannot get member of this ObjectValue - ObjectValue.PermanentReference is null");
}
MemberInfo memberInfo = this.memberFromNameMap.GetValue(key);
if (memberInfo == null) {
throw new DebuggerVisualizerException("Cannot get member value - no member found with name " + key);
}
property = createPropertyFromValue(key, this.PermanentReference.GetMemberValue(memberInfo));
this.properties.Add(key, property);
}
return property;
}
//set { properties[key] = value; }
} }
public static ObjectValue Create(Debugger.Value value, DebugType type, BindingFlags bindingFlags) public static ObjectValue Create(Debugger.Value value, Dictionary<string, MemberInfo> memberFromName)
{ {
ObjectValue result = new ObjectValue(); ObjectValue result = new ObjectValue(memberFromName);
foreach(MemberInfo memberInfo in value.Type.GetMembers(bindingFlags))
{
Value memberValue = value.GetMemberValue(memberInfo);
ObjectProperty property = new ObjectProperty(); // remember PermanentReference for expanding IEnumerable
property.Name = memberInfo.Name; Value permanentReference = value.GetPermanentReference();
// property.Expression = ?.Age result.PermanentReference = permanentReference;
// - cannot use expression,
// if the value is returned from an enumerator, it has no meaningful expression // cannot use GetMemberValues because memberValue does not have CodeTail anymore - we need the name of the member
property.IsAtomic = memberValue.Type.IsPrimitive; /*foreach(MemberInfo memberInfo in permanentReference.Type.GetMembers(bindingFlags))
property.IsNull = memberValue.IsNull; {
//property.Value = memberValue.AsString; Value memberValue = permanentReference.GetMemberValue(memberInfo);
property.Value = memberValue.IsNull ? "" : memberValue.InvokeToString(); result.properties.Add(createPropertyFromValue(memberInfo.Name, memberValue));
result.properties.Add(property.Name, property); }*/
}
return result; return result;
} }
public static ObjectValue Create(Expression expr, DebugType type, BindingFlags bindingFlags) private static ObjectProperty createPropertyFromValue(string propertyName, Value value)
{
ObjectProperty property = new ObjectProperty();
property.Name = propertyName;
// property.Expression = ?.Age
// - cannot use expression,
// if the value is returned from an enumerator, it has no meaningful expression
property.IsAtomic = value.Type.IsPrimitive;
property.IsNull = value.IsNull;
property.Value = value.IsNull ? "" : value.InvokeToString();
return property;
}
/*public static ObjectValue Create(Expression expr, DebugType type, BindingFlags bindingFlags)
{ {
ObjectValue result = new ObjectValue(); ObjectValue result = new ObjectValue();
foreach(MemberInfo memberInfo in type.GetMembers(bindingFlags)) foreach(MemberInfo memberInfo in type.GetMembers(bindingFlags))
@ -69,6 +106,6 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
result.properties.Add(property.Name, property); result.properties.Add(property.Name, property);
} }
return result; return result;
} }*/
} }
} }

27
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/EnumerableValuesProvider.cs

@ -17,23 +17,11 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
/// <summary> /// <summary>
/// Provides <see cref="ObjectValue"/>s for debugee objects implementing IEnumerable. /// Provides <see cref="ObjectValue"/>s for debugee objects implementing IEnumerable.
/// </summary> /// </summary>
public class EnumerableValuesProvider public class EnumerableValuesProvider : GridValuesProvider
{ {
private readonly Debugger.MetaData.BindingFlags bindingFlags =
BindingFlags.Public | BindingFlags.Instance | BindingFlags.Field | BindingFlags.GetProperty;
//private WindowsDebugger debugger;
private Expression targetObject;
private DebugType iEnumerableType;
private DebugType itemType;
public EnumerableValuesProvider(Expression targetObject, DebugType iEnumerableType, DebugType itemType) public EnumerableValuesProvider(Expression targetObject, DebugType iEnumerableType, DebugType itemType)
:base(targetObject, iEnumerableType, itemType)
{ {
this.targetObject = targetObject;
this.iEnumerableType = iEnumerableType;
this.itemType = itemType;
this.itemsSource = enumerateItems(); this.itemsSource = enumerateItems();
} }
@ -43,14 +31,9 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
get { return this.itemsSource; } get { return this.itemsSource; }
} }
public IList<MemberInfo> GetItemTypeMembers()
{
return itemType.GetMembers(this.bindingFlags);
}
private IEnumerable<ObjectValue> enumerateItems() private IEnumerable<ObjectValue> enumerateItems()
{ {
MethodInfo enumeratorMethod = iEnumerableType.GetMethod("GetEnumerator"); MethodInfo enumeratorMethod = collectionType.GetMethod("GetEnumerator");
Value enumerator = targetObject.Evaluate(WindowsDebugger.CurrentProcess).InvokeMethod(enumeratorMethod, null).GetPermanentReference(); Value enumerator = targetObject.Evaluate(WindowsDebugger.CurrentProcess).InvokeMethod(enumeratorMethod, null).GetPermanentReference();
MethodInfo moveNextMethod = enumerator.Type.GetMethod("MoveNext"); MethodInfo moveNextMethod = enumerator.Type.GetMethod("MoveNext");
@ -58,8 +41,8 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
while ((bool)enumerator.InvokeMethod(moveNextMethod, null).PrimitiveValue) while ((bool)enumerator.InvokeMethod(moveNextMethod, null).PrimitiveValue)
{ {
Value currentValue = enumerator.GetPropertyValue(currentproperty).GetPermanentReference(); Value currentValue = enumerator.GetPropertyValue(currentproperty);
yield return ObjectValue.Create(currentValue, this.itemType, this.bindingFlags); yield return ObjectValue.Create(currentValue, this.memberFromNameMap);
} }
} }
} }

50
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/GridValuesProvider.cs

@ -0,0 +1,50 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Martin Koníèek" email="martin.konicek@gmail.com"/>
// <version>$Revision$</version>
// </file>
using Debugger.MetaData;
using Debugger.AddIn.Visualizers.Utils;
using System;
using System.Collections;
using System.Collections.Generic;
using ICSharpCode.SharpDevelop.Services;
using ICSharpCode.NRefactory.Ast;
namespace Debugger.AddIn.Visualizers.GridVisualizer
{
/// <summary>
/// Provides <see cref="ObjectValue"/>s to be displayed in Grid visualizer.
/// Descandants implement getting values for IList and IEnumerable.
/// </summary>
public class GridValuesProvider
{
protected readonly Debugger.MetaData.BindingFlags memberBindingFlags =
BindingFlags.Public | BindingFlags.Instance | BindingFlags.Field | BindingFlags.GetProperty;
/// <summary> Used to quickly find MemberInfo by member name - DebugType.GetMember(name) uses a loop to search members </summary>
protected Dictionary<string, MemberInfo> memberFromNameMap;
protected Expression targetObject;
protected DebugType collectionType;
protected DebugType itemType;
public GridValuesProvider(Expression targetObject, DebugType collectionType, DebugType itemType)
{
this.targetObject = targetObject;
this.collectionType = collectionType;
this.itemType = itemType;
this.memberFromNameMap = this.GetItemTypeMembers().MakeDictionary(memberInfo => memberInfo.Name);
}
/// <summary>
/// Gets members that will be displayed as columns.
/// </summary>
public IList<MemberInfo> GetItemTypeMembers()
{
return itemType.GetMembers(this.memberBindingFlags);
}
}
}

26
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs

@ -18,23 +18,14 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
/// <summary> /// <summary>
/// Provides <see cref="ObjectValue"/>s for debugee objects implementing IList. /// Provides <see cref="ObjectValue"/>s for debugee objects implementing IList.
/// </summary> /// </summary>
public class ListValuesProvider : IListValuesProvider<ObjectValue> public class ListValuesProvider : GridValuesProvider, IListValuesProvider<ObjectValue>
{ {
private readonly Debugger.MetaData.BindingFlags bindingFlags =
BindingFlags.Public | BindingFlags.Instance | BindingFlags.Field | BindingFlags.GetProperty;
private Expression targetObject;
private DebugType iListType;
private DebugType listItemType;
private bool countEvaluated = false; private bool countEvaluated = false;
private int count = -1; private int count = -1;
public ListValuesProvider(Expression targetObject, DebugType iListType, DebugType listItemType) public ListValuesProvider(Expression targetObject, DebugType iListType, DebugType listItemType)
:base(targetObject, iListType, listItemType)
{ {
this.targetObject = targetObject;
this.iListType = iListType;
this.listItemType = listItemType;
} }
public int GetCount() public int GetCount()
@ -50,14 +41,9 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
public ObjectValue GetItemAt(int index) public ObjectValue GetItemAt(int index)
{ {
return ObjectValue.Create( return ObjectValue.Create(
targetObject.AppendIndexer(index).Evaluate(WindowsDebugger.CurrentProcess).GetPermanentReference(), targetObject.AppendIndexer(index).Evaluate(WindowsDebugger.CurrentProcess),
//targetObject.AppendIndexer(index), // don't use PermanentReference - possible only for IList though //targetObject.AppendIndexer(index), // use Expression instead of value - possible only for IList though
this.listItemType, this.bindingFlags); this.memberFromNameMap);
}
public IList<MemberInfo> GetItemTypeMembers()
{
return listItemType.GetMembers(this.bindingFlags);
} }
// TODO move to Utils iListType.EvaluateCount(Expression targetObject) // TODO move to Utils iListType.EvaluateCount(Expression targetObject)
@ -65,7 +51,7 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
// or targetObject.EvaluateIListCount() <- calls ResolveIListImplementation // or targetObject.EvaluateIListCount() <- calls ResolveIListImplementation
private int evaluateCount() private int evaluateCount()
{ {
PropertyInfo countProperty = iListType.GetGenericInterface("System.Collections.Generic.ICollection").GetProperty("Count"); PropertyInfo countProperty = this.collectionType.GetGenericInterface("System.Collections.Generic.ICollection").GetProperty("Count");
try { try {
// Do not get string representation since it can be printed in hex later // Do not get string representation since it can be printed in hex later
Value countValue = targetObject.Evaluate(WindowsDebugger.CurrentProcess).GetPropertyValue(countProperty); Value countValue = targetObject.Evaluate(WindowsDebugger.CurrentProcess).GetPropertyValue(countProperty);

3
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/VirtualizingIEnumerable.cs

@ -13,7 +13,8 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
/// <summary> /// <summary>
/// A wrapper around IEnumerable&lt;T&gt; with RequestNextItems method for pulling additional items /// A wrapper around IEnumerable&lt;T&gt; with RequestNextItems method for pulling additional items
/// from the IEnumerable&lt;T&gt; when needed. /// from the IEnumerable&lt;T&gt; when needed.
/// Can be used as source for LazyListView. /// Can be used as source for <see cref="LazyListView" />.
/// (Used to wrap EnumerableValuesProvider.ItemsSource)
/// </summary> /// </summary>
public class VirtualizingIEnumerable<T> : ObservableCollection<T> public class VirtualizingIEnumerable<T> : ObservableCollection<T>
{ {

2
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/PresentationBindings/GridViewColumnHider.cs

@ -18,7 +18,7 @@ namespace Debugger.AddIn.Visualizers
} }
/// <summary> /// <summary>
/// Utility for hiding and showing columns in GridView (GridViewColumn does not have Visility). /// Utility for hiding and showing columns in GridView (GridViewColumn does not have Visility property).
/// </summary> /// </summary>
public class GridViewColumnHider public class GridViewColumnHider
{ {

41
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/PresentationBindings/ScrollUtils.cs

@ -0,0 +1,41 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Martin Koníèek" email="martin.konicek@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace Debugger.AddIn.Visualizers
{
/// <summary>
/// Description of ScrollUtils.
/// </summary>
public static class ScrollUtils
{
/// <summary>
/// Searches VisualTree of given object for a ScrollViewer.
/// </summary>
public static ScrollViewer GetScrollViewer(this DependencyObject o)
{
var scrollViewer = o as ScrollViewer;
if (scrollViewer != null) {
return scrollViewer;
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++)
{
var child = VisualTreeHelper.GetChild(o, i);
var result = GetScrollViewer(child);
if (result != null) {
return result;
}
}
return null;
}
}
}

48
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/IEnumerableExtensions.cs

@ -0,0 +1,48 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Martin Koníèek" email="martin.konicek@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System.Collections.Generic;
using System.Linq;
using System;
namespace Debugger.AddIn.Visualizers.Utils
{
public static class IEnumerableExtensions
{
/// <summary>
/// Builds Dictionary for quickly searching a collection.
/// The keys must be unique.
/// </summary>
/// <param name="collection">Collection for which to build Dictionary.</param>
/// <param name="keySelector">Function returning key by which to index.</param>
public static Dictionary<K, V> MakeDictionary<K, V>(this IEnumerable<V> collection, Func<V, K> keySelector)
{
Dictionary<K, V> dictionary = new Dictionary<K, V>();
foreach (V item in collection)
{
K key = keySelector(item);
if (dictionary.ContainsKey(key)) throw new InvalidOperationException("MakeDictionary: key " + key + " seen twice");
dictionary[key] = item;
}
return dictionary;
}
/// <summary>
/// Builds Lookup for quickly searching a collection.
/// </summary>
/// <param name="collection">Collection for which to build Dictionary.</param>
/// <param name="keySelector">Function returning key by which to index.</param>
public static Lookup<K, V> MakeLookup<K, V>(this IEnumerable<V> collection, Func<V, K> keySelector)
{
Lookup<K, V> lookup = new Lookup<K, V>();
foreach (V item in collection)
{
lookup.Add(keySelector(item), item);
}
return lookup;
}
}
}

21
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/Lookup.cs

@ -14,11 +14,12 @@ namespace Debugger.AddIn.Visualizers.Utils
/// </summary> /// </summary>
public class Lookup<TKey, TValue> public class Lookup<TKey, TValue>
{ {
private Dictionary<TKey, LookupValueCollection<TValue>> _dictionary; /// <summary>Wrapped dictionary</summary>
private Dictionary<TKey, LookupValueCollection<TValue>> dictionary;
public Lookup() public Lookup()
{ {
_dictionary = new Dictionary<TKey, LookupValueCollection<TValue>>(); dictionary = new Dictionary<TKey, LookupValueCollection<TValue>>();
} }
public LookupValueCollection<TValue> this[TKey key] public LookupValueCollection<TValue> this[TKey key]
@ -26,7 +27,7 @@ namespace Debugger.AddIn.Visualizers.Utils
get get
{ {
LookupValueCollection<TValue> values = null; LookupValueCollection<TValue> values = null;
if (_dictionary.TryGetValue(key, out values)) if (dictionary.TryGetValue(key, out values))
{ {
return values; return values;
} }
@ -36,13 +37,13 @@ namespace Debugger.AddIn.Visualizers.Utils
public void Add(TKey key, TValue value) public void Add(TKey key, TValue value)
{ {
LookupValueCollection<TValue> values = null;; LookupValueCollection<TValue> values = null;
if (!_dictionary.TryGetValue(key, out values)) if (!dictionary.TryGetValue(key, out values))
{ {
values = new LookupValueCollection<TValue>(); values = new LookupValueCollection<TValue>();
_dictionary.Add(key, values); dictionary.Add(key, values);
} }
values.Add(value); values.Add(value);
} }
} }
} }

Loading…
Cancel
Save