I have the method
HandleNotification(string message, Dictionary<string, object> additionalData, bool isActive)
and I would take the from additionalData the value.
I have this additional data:
Extracoins:4
I don't understand how I can take the value 4 from additionalData for a specific key Extracoins.
You can get a value from a Dictionary like this if your only interested in accessing one specific key.
object value = null;
additionalData.TryGetValue("Extracoins", out value);
That way object will be the value in the Dictionary or it will remain null if the value is not found.
Or you can do:
if (additionalData.ContainsKey("Extracoins"))
{
object value = additionalData["Extracoins"];
}
Finally if you wanted to iterate over all the values in the Dictionary until you get the correct value you could do:
object value = null;
foreach (KeyValuePair<string, object> pair in additionalData)
{
if (pair.Key == "Extracoins")
{
value = pair.Value;
}
}
Related
I am trying to add value to an outer variable val_dict from if and else block in the for loop. The problem is that the output type from if block is different from the output type of else block which throws a type error for either of them if i initialize the variable to one of the output type classes.
In short the val_dict is an object that can either be a dictionary<string,object> or a null object, but some how i cannot seem to define a common type for both of these object types.
here is the code:
Dictionary<string, Dictionary<string,object>> data_dict =
new Dictionary<string, Dictionary<string, object>>();
foreach (KeyValuePair<(string, string), object> cat_nam_val in dataset)
{
var val_dict = new Dictionary<string, object>(); //use val_dict as dictionary or object
if (target_survey_id != null)
{
data_dict[target_survey_id].TryGetValue(cat_nam_val.Key.Item1, out val_dict);
}
else
{
data_dict.TryGetValue(cat_nam_val.Key.Item1, out val_dict);
}
if (IsDictionary(val_dict));
{
val_dict[cat_nam_val.Key.Item2] = cat_nam_val.Value; //generate new dict becoz val_dict is an object so cannot be indexed
}
}
You cannot coerce types when using out. As a result, you can use a temporary out variable and then cast it if you are certain that it is a dictionary.
foreach (KeyValuePair<(string, string), object> cat_nam_val in dataset)
{
var val_dict = new Dictionary<string, object>(); //use val_dict as dictionary or object
if (target_survey_id != null)
{
// use a temporary variable to work around type mismatch
data_dict[target_survey_id].TryGetValue(cat_nam_val.Key.Item1, out var temp_val_dict);
// if you know that object is a dictionary, cast and assign
val_dict = (Dictionary<string, object>)temp_val_dict;
}
else
{
data_dict.TryGetValue(cat_nam_val.Key.Item1, out val_dict);
}
if (IsDictionary(val_dict))
{
val_dict[cat_nam_val.Key.Item2] = cat_nam_val.Value; //generate new dict becoz val_dict is an object so cannot be indexed
}
}
I have received data of type object {System.Collections.Generic.Dictionary<string, object>}. Parsing this is pretty straightforward:
Dictionary<string, object> parsedData = data as Dictionary<string, object>;
Now I am trying to access parsedData["stringArr"] of type object {object[]}. I got stuck when trying to convert this object {object[]} to string[].
I can't even iterate this:
foreach (object o in parsedData["stringArr"]){}
//returns Exception("...'object' does not contain a public instance definition for GetEnumerator")
One way you could get the object values as string[] is to use the as cast, just like you did with the original data:
object data = new Dictionary<string, object>
{
{"stringArr", new[] {"item1", "item2", "item3"}},
};
var parsedData = data as Dictionary<string, object>;
// cast the object values to string[]
foreach (var o in parsedData["stringArr"] as string[])
{
Console.WriteLine(o);
}
// Output:
// item1
// item2
// item3
That's because parsedData["stringArr"] is an object, not a object[].
I think you want to change the dictionary type parameters:
Dictionary<string, object[]> parsedData = data as Dictionary<string, object[]>;
If you have a Dictionary<string, object>, and you know a particular key's value has a more specific type, cast it as that type:
foreach (string s in (string[])parsedData["stringArr"])
You will of course receive exceptions if the value at that key is not of that type. A "safer" way of doing it would be to check first:
if (parsedData["stringArr"] as string[] data != null)
{
foreach (string s in data)
{
...
}
}
First of all, thank you all for your energy to help me to solve it. I would just bash my keyboard for a few more hours without you. I can't understand why extra conversion to object[] is required yet, but what works is:
Dictionary<string, object> parsedData = data as Dictionary<string, object>;
if (parsedData.ContainsKey("stringArr"))
{
foreach (object o in parsedData["stringArr"] as object[])
{
string myString = o.ToString();
}
}
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 and Value are copied from Dictionary's internal structures (Entry[]) to new instances of KeyValuePair or DictionaryEntry. Therefore trying to modify these DictionaryEntry is futile, because these changes are not propagated back to the dictionary. To modify Dictionary, you have to use it's indexer or Add, 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 an index argument when setting new value to the Dictionary using it's Item property. Creating a key setter is more difficult, because Dictionary doesn't support changing of existing key. What you have to do is actually remove existing item from the Dictionary and insert a new one with the new key:
// Dictionary.Item property we will use to get/set values
var itemProp = target.GetType().GetProperty("Item");
// Since you want to modify dictionary while enumerating it's items (which is not allowed),
// you have to use .Cast<object>().ToList() to temporarily store all items in the list
foreach (var item in (target as IEnumerable).Cast<object>().ToList())
{
// item is of type KeyValuePair<TKey,TValue> and has Key and Value properties.
// Use reflection to read content from the Key property
var itemKey = item.GetType().GetProperty("Key").GetValue(item);
Action<Object> valueSetter = (val) => itemProp.SetValue(target, val, new object[] { itemKey });
// valueSetter(someNewValue);
// It's not possible to just change the key of some item. As a workaround,
// you have to remove original item from the dictionary and insert a new item
// with the original value and with a new key.
Action<Object> keySetter = (key) =>
{
// read value from the dictionary for original key
var val = itemProp.GetValue(target, new object[] { itemKey });
// set this value to the disctionary with the new key
itemProp.SetValue(target, val, new object[] { key });
// remove original key from the Dictionary
target.GetType().GetMethod("Remove").Invoke(target, new Object[] { itemKey });
// need to "remember" the new key to allow the keySetter to be called repeatedly
itemKey = key;
};
// keySetter(someNewKey);
}
In my desktop C# application I start with a dictionary. I want to be able to check this dictionary for a key. If the dictionary has this key, I would like to pass it on to a method. If the dictionary doesn't have this key, I would like to create a blank list and just pass that on instead. How can I do this?
I get the error "given key was not present in the dictionary". Can I add a default so it is never null maybe?
// myDic was declared as a Dictionary<string, List<string>
// Here is how I call someFunction
string text = SomeFunction(stringValue1, stringValue2, myDic[field1.field2]);
// SomeFunction looks like this
string SomeFunction (string string1, string string2, List<string> ra)
{
// method
return stringResult;
}
Updated based on comments. To pass one key that may or may not exist you may do this(assuming the value is a List):
// assuming the method we are calling is defined like this:
// public String SomeFunction(string string1, String string2, List<String> ra)
List<string> valueToPassOn;
if (_ra.ContainsKey(lc.Lc))
{
valueToPassOn = _ra[lc.Lc]
}
else
{
valueToPassOn = new List<string>();
}
string text = tooltip.SomeFunction(something1, something2, valueToPassOn);
Should you want to pass an entire dictionary (as the question originally read), regardless of whether or not the dictionary exists:
You have two options. Either create the dictionary regardless like this:
if (myDic == null)
{
// change var and var2 to the types of variable they should be, ex:
myDic = new Dictionary<string, List<string>>();
}
string text = SomeFunction(stringValue1, stringValue2, myDic);
or, what is probably the better option, in the declaration of the function SomeFunction add a dictionary as a variable with a default parameter. Just be sure that your function knows what to do if the dictionary is null.
string SomeFunction(string string1, string string2, Dictionary dictionary = null)
{
// method here
}
You can check if the key exists using ContainsKey method and if it returns false you can pass a default value you want:
// replace default(string) with the value you want to pass
// if the key doesn't exist
var value = myDic.ContainsKey(field1.field2) ? myDic[field1.field2] : default(string);
string text = SomeFunction(stringValue1, stringValue2, value);
What you need to do is make sure the dictionary actually contains the given key in the dictionary.
If you need to extract the value by key, use TryGetValue method:
string value;
if (myDict.TryGetValue(key, out value))
{
// Key exists in the dictionary, do something with value.
}
Use one of the following snippets in order to check if dictionary is empty and take some action:
var x = new Dictionary<string, string>();
if (x.Any())
{
//....
}
if (x.ContainsKey("my key"))
{
}
if (x.ContainsValue("my value"))
{
}
if (x.Count > 0)
{
}
The object Row is a class, that has a property Values which is a Dictionary.
Below are extension methods on the Values property.
public static T TryGetValue<T>(this Row row, string key)
{
return TryGetValue(row, key, default(T));
}
public static T TryGetValue<T>(this Row row, string key, T defaultValue)
{
object objValue;
if (row.Values.TryGetValue(key, out objValue))
{
return (T)objValue;
}
return defaultValue;
}
If I do:
user.Username = user.Values.TryGetValue<string>("Username");
This happends if the key "username" is not in the Dictionary.
I get an exception, invalid cast:
The following error ocurred:
System.InvalidCastException: Specified cast is not valid.
TryGetValue[T](Row row, String key, T defaultValue)
TryGetValue[T](Row row, String key)
So I guess TryGetValue doesn't work on strings?
Is it possible you've got an entry in your dictionary with key "Username" whose value is not a string?
I've added comments to your method explaining how this could lead to your issue.
// I'm going to go ahead and assume your Values property
// is a Dictionary<string, object>
public static T TryGetValue<T>(this Row row, string key, T defaultValue)
{
// objValue is declared as object, which is fine
object objValue;
// this is legal, since Values is a Dictionary<string, object>;
// however, if TryGetValue returns true, it does not follow
// that the value retrieved is necessarily of type T (string) --
// it could be any object, including null
if (row.Values.TryGetValue(key, out objValue))
{
// e.g., suppose row.Values contains the following key/value pair:
// "Username", 10
//
// then what you are attempting here is (string)int,
// which throws an InvalidCastException
return (T)objValue;
}
return defaultValue;
}
It should work fine, either if the key "Username" is in the dictionary with a corresponding string value, or not in the dictionary at all.
The fact that you're getting an InvalidCastException shows that the value for the "Username" key wasn't a string.