I'm trying to get the setter function of a dictionary item value. I know the object is a Dictionary< TKey,TValue>, but I don't know the types of Tkey and TValue, so I think my only resort is to use an IDictionary.
In pseudo code, I want to do something like this;
Action<object> keySetter = dictionary.items[index].value.setter
Action<object> valueSetter = dictionary.items[index].key.setter
Unfortunately the IDictionary has no indexer and I'm not sure how to get to the actual keys and values.
Right now I'm looping through the dictionary entries and get the setter from that, but whenever I call the setter it doesn't seem to change to value in the dictionary. So I suspect the DictionaryEntry is a copy and doesn't point to the actual value in the dictionary.
//for simplicity sake a Dictionary is added here, but usually the TKey and Tvalue are not known
IDictionary target = new Dictionary<int, string>();
target.Add( 0, "item 1" );
foreach ( DictionaryEntry dictionaryEntry in target )
{
//want to get the setter for the item's key setter and value setter
PropertyInfo keyProperty = dictionaryEntry.GetType().GetProperty( "Key" );
PropertyInfo valueProperty = dictionaryEntry.GetType().GetProperty( "Value" );
Action<object> keySetter = ( val ) =>
{
keyProperty.SetMethod.Invoke( dictionaryEntry, new object[] { val } );
};
Action<object> valueSetter = ( val ) =>
{
valueProperty.SetMethod.Invoke( dictionaryEntry, new object[] { val } );
};
keySetter.Invoke( 1 );
valueSetter.Invoke( "item 1 value succesfully modified" );
Console.WriteLine( target.Keys ); //no change
Console.WriteLine( target.Values ); //no change
}
Since I do know that the IDictionary is actually a Dictionary< TKey, TValue> underneath, maybe I can do some reflection magic to get the setter that way?
When you enumerate entries of a
Dictionary
,Key
andValue
are copied fromDictionary
's internal structures (Entry[]
) to new instances ofKeyValuePair
orDictionaryEntry
. Therefore trying to modify theseDictionaryEntry
is futile, because these changes are not propagated back to the dictionary. To modifyDictionary
, you have to use it's indexer orAdd
,Remove
or similar methods.C# indexers are just a syntactic sugar to use the Dictionary<TKey,TValue>.Item property. So when using reflection, you have to use this property instead.
To create value setter for each item in a
Dictionary
, you need to get a key for each of these items and then use it as anindex
argument when setting new value to theDictionary
using it'sItem
property. Creating a key setter is more difficult, becauseDictionary
doesn't support changing of existing key. What you have to do is actually remove existing item from theDictionary
and insert a new one with the new key: