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,KeyandValueare copied fromDictionary's internal structures (Entry[]) to new instances ofKeyValuePairorDictionaryEntry. Therefore trying to modify theseDictionaryEntryis futile, because these changes are not propagated back to the dictionary. To modifyDictionary, you have to use it's indexer orAdd,Removeor 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 anindexargument when setting new value to theDictionaryusing it'sItemproperty. Creating a key setter is more difficult, becauseDictionarydoesn't support changing of existing key. What you have to do is actually remove existing item from theDictionaryand insert a new one with the new key: