Is it possible to access properties of Generic types?

E

Ethan Strauss

I have a Class "Multidictionary" which I created which is basically a
dictionary which can have multiple values for the same key. The class centers
around
private Dictionary<K, List<V>> _InnerDictionary;
and provides methods to add to the InnerDictionary, remove from the
InnerDictionary and so forth.
I would like to have methods which allow me to retrieve or renmove single
value items based on a specific value of one pf their properties. I can't
figure out how to be able to examine the values of properties of a geneic
type. I suspect that it is possible with Reflection, but I can't find.


What I am thinking of is something like:

public void RemoveItemsWithSpecificValuePropertyValue(P
comparisonValue)
{
foreach (K key in _InnerDictionary)
{
foreach (V value in K)
{
if (value.P == comparisonValue)//This is the part that I
don't know how to do
{
// Remove value from list
}
}
}
}

Thanks for any help!
Ethan
 
I

Ignacio Machin ( .NET/ C# MVP )

I have a Class "Multidictionary" which I created which is basically a
dictionary which can have multiple values for the same key. The class centers
around
        private Dictionary<K, List<V>> _InnerDictionary;

Yep, that is how it;s done

one qeustion though, where is your class defined ???
In the code above you are simply using the Dictionary class provided
by the framework

Of course you can do it with reflection, the fact that It's "generic"
has nothing to do., if you have something like

note that this code was written in the google's editor, not tested or
compiled

class MyDir<TKey, TValue>: Dictionary<Tkey, TValue>{

public object FindByProperty( TKey key, string pName ){
//decide if TValue is enumerable or no
if ( this[TKey] is IEnumerable )
{
foreach(object o in (IEnumerable) this[TKey] )
if ( HasValue( o, pName ) )
return o;
}
else
return HasValue ( this[TKey], pName ) ? this[TKey]: null;
}

HasValue( object o, string propertyName )
{
// use reflection to get the value
}

}
 
E

Ethan Strauss

Thanks!
Can you expand on your "HasValue" method? I have never used reflection I
can't figure that bit out. I think I can handle the rest once I get that.
Ethan

Ignacio Machin ( .NET/ C# MVP ) said:
Yep, that is how it;s done

one qeustion though, where is your class defined ???
In the code above you are simply using the Dictionary class provided
by the framework
I didn't show most of the code for the class. The rest is constructors and
methods to interact with that dictionary.
Of course you can do it with reflection, the fact that It's "generic"
has nothing to do., if you have something like

note that this code was written in the google's editor, not tested or
compiled

class MyDir<TKey, TValue>: Dictionary<Tkey, TValue>{

public object FindByProperty( TKey key, string pName ){
//decide if TValue is enumerable or no
if ( this[TKey] is IEnumerable )
{
foreach(object o in (IEnumerable) this[TKey] )
if ( HasValue( o, pName ) )
return o;
}
else
return HasValue ( this[TKey], pName ) ? this[TKey]: null;
}

HasValue( object o, string propertyName )
{
// use reflection to get the value
}

}
and provides methods to add to the InnerDictionary, remove from the
InnerDictionary and so forth.
I would like to have methods which allow me to retrieve or renmove single
value items based on a specific value of one pf their properties. I can't
figure out how to be able to examine the values of properties of a geneic
type. I suspect that it is possible with Reflection, but I can't find.

What I am thinking of is something like:

public void RemoveItemsWithSpecificValuePropertyValue(P
comparisonValue)
{
foreach (K key in _InnerDictionary)
{
foreach (V value in K)
{
if (value.P == comparisonValue)//This is the part that I
don't know how to do
{
// Remove value from list
}
}
}
}

Thanks for any help!
Ethan
 
J

jp2msft

foreach (K key in _InnerDictionary) {
foreach (V value in K) {
if (value.P == comparisonValue) {
// This is the part that I don't know how to do
// Remove value from list
}
}
}

I don't think you can do this. What you would want is to call the
"value.Remove()" method, but this would cause problems in your itteration.

Instead, look into something like this *untested* code:

for (int i = 0; i < _InnerDictionary.Count; i++) {
for (int j = 0; j < K.Count; j++) {
if (K[j].P == comparisonValue) {
K[j].Remove();
// or
_InnerDictionary.Item.Remove();
}
}
}
 
P

parez

I have a Class "Multidictionary" which I created which is basically a
dictionary which can have multiple values for the same key. The class centers
around
private Dictionary<K, List<V>> _InnerDictionary;
and provides methods to add to the InnerDictionary, remove from the
InnerDictionary and so forth.
I would like to have methods which allow me to retrieve or renmove single
value items based on a specific value of one pf their properties. I can't
figure out how to be able to examine the values of properties of a geneic
type. I suspect that it is possible with Reflection, but I can't find.

What I am thinking of is something like:

public void RemoveItemsWithSpecificValuePropertyValue(P
comparisonValue)
{
foreach (K key in _InnerDictionary)
{
foreach (V value in K)
{
if (value.P == comparisonValue)//This is the part that I
don't know how to do
{
// Remove value from list
}
}
}
}

Thanks for any help!
Ethan

What i think you are looking for is a constraint.
where V : (Some class which is a base class for your Vs or an
interface implemnted by V which has the property P)
 
M

Marc Gravell

You might be better-off with a "predicate" approach... this would let
the caller decide what are useful conditions to remove items, and
ensures type-safety while removing the need for reflection - for
example see below.

[example uses C# 3; if you don't have VS2008 let me know - the
approach is fine for C# 2 and .NET 2.0]

Marc

using System;
using System.Collections.Generic;
class Foo
{
public string Bar { get; set; }
public int Whatever { get; set; }
}
static class Program
{
static void Main()
{
var dict = new MultiDictionary<string, Foo>();
dict.Add("abc", new Foo { Bar = "item 1", Whatever = 4 });
dict.Add("def", new Foo { Bar = "item 2", Whatever = 4 });
dict.Add("abc", new Foo { Bar = "item 3", Whatever = 3 });
dict.Add("abc", new Foo { Bar = "item 4", Whatever = 9 });
dict.Add("ghi", new Foo { Bar = "item 5", Whatever = 4 });
int removed = dict.RemoveAll(foo => foo.Whatever == 4);
}
}
class MultiDictionary<TKey, TValue>
{
public void Add(TKey key, TValue value)
{
List<TValue> items;
if (!list.TryGetValue(key, out items))
{
items = new List<TValue>();
list.Add(key, items);
}
items.Add(value);
}
public int RemoveAll(Predicate<TValue> match)
{
List<TKey> killKeys = new List<TKey>();
int count = 0;
// remove all matching items, noting any sub-lists
// that are now empty
foreach (var pair in list)
{
count += pair.Value.RemoveAll(match);
if (pair.Value.Count == 0) killKeys.Add(pair.Key);
}
// remove the empty sub-lists
foreach (TKey killKey in killKeys)
{
list.Remove(killKey);
}
return count;
}
private Dictionary<TKey, List<TValue>> list;

public MultiDictionary() : this(null) { }
public MultiDictionary(IEqualityComparer<TKey> comparer)
{
list = new Dictionary<TKey, List<TValue>>(
comparer ?? EqualityComparer<TKey>.Default);
}
}
 
E

Ethan Strauss

Thanks Marc,
This approach looks very promising. I am using VS2005 (.Net 2.0), but I
think you have given enough direction to get me where I want to go.
Ethan
 
M

Marc Gravell

I should add that there is an "EditableLookup<TKey,TValue>" that I
wrote, in Jon Skeet's "MiscUtil" and acts in a similar manner.
http://www.pobox.com/~skeet/csharp/miscutil

This maps to the .NET 3.5 ILookup<TKey,TValue> interface (and the
immutable Lookup<TKey,TValue> class), but IIRC it also compiles
in .NET 2.0 [we tried to get as much as possible to play nicely
with .NET 2.0]; I don't think it has a RemoveAll(predicate) method at
the moment, but it might make a useful starting point.

Marc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top