How to access the values in a dynamic dictionary in C#? - c#

I have a dictionary which is dynamically generated. In the dictionary, for a single Key, there are multiple values. I am trying to access one of the values in those multiple values. My code so far:
var result = new Dictionary<string, object>();
var dictionary = deserialisedResult as IDictionary<string, object>;
foreach (var item in dictionary)
{
result.Add(item.Key, item.Value);
}
object o = result;
string[] names = o.GetType().GetProperties().Select(p => p.Name).ToArray();
foreach (var prop in names)
{
object propValue = o.GetType().GetProperty(prop).GetValue(o, null);
var value = propValue.GetValue(o,null);
}
But this is not working.
I need to get the values for 'resource'.
When I add watch, I see it nested as such:

Following line is causing issue out here:
string[] names = o.GetType().GetProperties().Select(p => p.Name).ToArray();
GetType() for Object base class type will not yield a Type, which can provide the PropertyInfo[], that you are looking for, even otherwise you are trying to run it for Dictionary<string,object> type, which anyway doesn't have properties to help find the relevant information. For it the Type would always be Dictionary
What you need is fetch the key collection from Dictionary and use them to fetch the values stored in the Dictionary
foreach (var key in result.Keys)
{
var value = result[key];
}
Solution is based on code provided in the question, I am not sure if you have further requirements

Related

C# getting values from Dictionary<string, List<object>>

I have a question about how to get values from my Dictionary<string, List<object>>, I tried all examples which I found in google, but still can't get something readable value.....
so, here is the code:
List<object> listValues = new List<object>();
listValues.Add(risk);
listValues.Add(validFrom);
listValues.Add(effectiveDate);
Dictionary<string, List<object>> dic = new Dictionary<string, List<object>>();
dic.Add(nameOfInsuredObject, listValues);
foreach (object value in dic.Values)
{
System.Console.WriteLine(value);
}
I can get key from dictionary, but with getting value I am stucked now....
And here is the result of this code:
Key => testInsObj
Values => System.Collections.Generic.List`1[System.Object]
So can anyone help me with it? I am new in C#, so maybe this is easy questions for others....
It seems you are looking for writing values of the list this way:
foreach (var value in dic.Values)
{
value.ForEach(Console.WriteLine);
}
In fact each element of the Dictionary is <string, List<Object>>. So, when you want to write Value part of the pair to console, you need a for loop to write each element of the List<object>.
It is confusing for new C# users, how to access the dictionary.
When you do a foreach on the dictionary, you get a KeyValuePair<TKey, TValue>. Now this KeyValuePair<TKey, TValue>, has 2 properties KeyValuePair.Key and KeyValuePair.Value, representing the Key and Value stored in the dictionary.
Also, the Value in your case is a List<T>, which means doing a Console.WriteLine on it will not print the whole List<T> (as some people expect), but just some reference string. You will have to "loop" over the list to print individual elements. Needless to say, depending on what you want to do with the element in the List<T>, you can use LINQ or some other common C# idiom.
foreach (var value in dic) {
Console.WriteLine(value.Key);
foreach (var item in value.Value)
Console.WriteLine(item);
}

c# Dictionary<string,string> how to loop through items without knowing key [duplicate]

This question already has answers here:
How to iterate over a dictionary?
(29 answers)
Closed 8 years ago.
I have a:
var selectedDates = new Dictionary<string, string>();
selectedDates.Add("2014-06-21", DateTime.Now.ToLongDateString());
selectedDates.Add("2014-07-21", DateTime.Now.AddDays(5).ToLongDateString());
selectedDates.Add("2014-08-21", DateTime.Now.AddDays(9).ToLongDateString());
selectedDates.Add("2014-09-21", DateTime.Now.AddDays(14).ToLongDateString());
How can I loop trough items without knowing the key?
For example I want to get the value of the item[0]
If I do:
var item = selectedDates[0].value; // I get an error
How can I loop trough items without knowing the key?
For example I want to get the value of the item[0]
You want to treat the dictionary as (ordered) collection similar to a list or array and get the first item in it?
You can because a Dictionary<string, string> is an IEnumerable<KeyValuePair<string, string>> implicitly. Just use First or FirstOrDefault:
string valueAtFirstPosition = selectedDates.First().Value;
However, note that a dictionary is not meant to be used as as an ordered collection. It is a collection which can be used to fast-lookup a value by a key. But you can enumerate it anyway.
foreach(KeyValuePair<string, string>keyVal in selectedDates)
{
Console.WriteLine("Key: {0} Value: {1}", keyVal.Key, keyVal.Value);
}
You should simply not rely on that order. I think in the current implementation the order is stable as long as you don't delete items. Read
Read: Why is a Dictionary “not ordered”?
try this
foreach (string key in selectedDates.Keys)
{
var item = selectedDates[key];
}
It's simple, loop trough it with a foreach or to get a specific index do:
var date = selectedDates.ElementAt(0).Value;
Let me put together two things for you. Firstly, you can loop or use LINQ to access elements, just as you could do it in a list as well:
var dict = new Dictionary<string, string>();
// loop
foreach (var item in dict)
{
var key = item.Key;
var value = item.Value;
}
// "first" (see below)
var firstItem = dict.First();
However, be aware that what you're referring to as the first item can be pretty much any item in the Dictionary. Dictionaries store elements in any order that is convenient for a lookup (so do sets).
This order is known for some implementations, but lists or arrays might fit better when the order of the elements is important. A Dictionary in .NET is an implementation of a hash table data structure (tree map is another map implementation).
try this :
foreach(var key in selectedDates.Keys)
{
var value = selectedDates[key];
}
Use this overload of Where:
var result = selectedDates.Where((d,i)=>i==0);
Try:
foreach (var date in selectedDates)
{
var item = date.Value;
}

How to iterate through list of generic dictionary in C#

I have a json object which is been converted to list of Dictionary. The json is as follows:
{
"DataList":
{"Non Fuel":
{
"sn":"/DataXmlProduct/Customers/DataXml/Customer/DueDate",
"ItemCode":"/DataXmlProduct/Customers/DataXml/Customer/InvoiceNo",
"Qty":"/DataXmlProduct/Customers/DataXml/Customer/CustomerNo",
"Amount":"DataXml/Customer/TotalCurrentCharges"
},
"Fuel":{
"sn":"/DataXmlProduct/Customers/DataXml/Customer/InvoiceNo",
"ItemCode":"/DataXmlProduct/Customers/DataXml/Customer/InvoiceNo",
"Amount":"DataXml/Customer/TotalCurrentCharges"
}
}
}
The result is (Dictionary<string, object>), Here the value of each dictionary is again a dictionary and I need to dynamically iterate through each values of the dictionary and get the last key & value where the value is a Xpath and need to get the values from the xpath.
Kindly help me with a solution to iterate through the dictionary. It should be generic since the json format can vary based on user input.
Assuming that the actual values (such as the contents of fuel) come out as a KeyValuePair<string, object>, then you could do this with a recursive method:
public static void ParseData(object source)
{
Dictionary<string, object> Dict;
KeyValuePair<string, object> Kvp;
if ((Dict = source as Dictionary<string,object>) != null)
{
foreach(var kvp in Dict)
{
Console.WriteLine(kvp.Key);
ParseData(kvp.Value);
}
}
elseif ((Kvp = source as KeyValuePair<string, object>) != null)
{
Console.WriteLine("{0}{1}", Kvp.Key, Kvp.Value);
}
}
This makes an assumption or two, but that will iterate through all the data assuming its made of dictionaries and kvps.
Edit: If you've got an XPath and want to get a node then what you'll need to do is prepare an XMLDocument with the data in. You can use the code above to walk through the data to help you build an XMLDocument and then query the document with your XPath.
Here's the basic code for processing all the data:
static void IterateDictionary(Dictionary<string, object> dictionary)
{
foreach (var pair in dictionary)
{
System.Console.WriteLine("Processing key: " + pair.Key);
object value = pair.Value;
var subDictionary = value as Dictionary<string, object>;
if (subDictionary != null)
{
// recursive call to process embedded dictionary
// warning: stackoverflowexception might occur for insanely embedded data: dictionary in dictionary in dictionary in . etc
IterateDictionary(subDictionary);
}
else
{
// process data
System.Console.WriteLine("data: {0}", value);
}
}
}
hope this helps
i'll suggest using Json.NET to serialize your objects, however, you've mentioned that the input is dynamic, but are the attributes standardized? Looking at your sample, there are several repeated fields. You can deserialize the json into your classes by doing
JsonConvert.DeserializeObject<YOUR_CUSTOM_OBJECT>

Optimize Dictionary Add on ExpandoObjects in C#

I have an advanced program that retrieves data from a database and creates objects from the data via ExpandoObjects in C#.
I'm now in the process of optimizing my entire process but came upon a piece of code that was the bottleneck performance-wise. I am quite curious how far I can furhter optimize this piece of code and already managed to run it 3 times as fast by doing the following:
Seperated 'the finding 'types' section' in a seperate for loop and only iterate over it when it hasn't been initialized yet.
Added a case for when the value is null and create an empty string instead, since for some reason Dictionary.Add slows down quite a lot when adding Null values.
// Holds all objects that are created inside the object.
Dictionary<string, IDictionary<string, dynamic>> objects = new Dictionary<string, IDictionary<string, dynamic>>();
// This foreach loop is the slowest part!
foreach (KeyValuePair<string, dynamic> pair in fields)
{
string type = pair.Key.Split('_')[0];
IDictionary<string, dynamic> obj;
if (!objects.TryGetValue(type, out obj))
{
obj = new ExpandoObject();
objects.Add(type, obj);
}
int location = pair.Key.IndexOf(type + "_");
string key = pair.Key.Remove(location, type.Length + 1);
if (pair.Value == null) // If Value is null, replace it with an empty string (dictionary slows quite alot when passing it null values)
obj.Add(key, "");
else
obj.Add(key, pair.Value);
}
if (types == null)
types = objects.Select(x => x.Key).ToList();
I am wondering, how is it that dictionary slows down that much when adding Null values, is it that in the underlying structure it does special operations when encountering null values? And is there something I'm missing to further optimize the code?.
Any help is again greatly appreciated.
UPDATE
Edited the code with the most recent changes I've gathered from SO.
You can avoid the multiple lookups in the dictionary by using TryGetValue instead of ContainsKey:
foreach (KeyValuePair<string, dynamic> pair in fields)
{
string type = pair.Key.Split('_')[0];
IDictionary<string, dynamic> obj;
if (!objects.TryGetValue(type, out obj))
{
obj = new ExpandoObject();
objects.Add(type, obj);
}
int location = pair.Key.IndexOf(type + "_");
string key = pair.Key.Remove(location, type.Length + 1);
if (pair.Value == null)
obj.Add(key, "");
else
obj.Add(key, pair.Value);
}
BTW: I don't see you using types in that second foreach loop. Therefore you can replace the first foreach loop with this simple code:
types = objects.Select(x => x.Key).ToList();
This should save quite a lot of time as it removes the slow search in the types list and the double parsing of the types.
Obviously this needs to be put after the foreach loop I showed above.

Convert KeyValuePair to anonymous type in a LINQ query

I have an IEnumerable<KeyValuePair<string,string>>, from which I would like, ideally, an anonymous object which has the keys as property names and the values as property values.
I've tried various selection expressions (none of which even compiled...) and an approach using ExpandoObject (see below), but without success. Is there a good way to do this? If possible, I'd like to avoid an extra explicit iteration over the collection (i.e. do it all with a LINQ statement of some sort).
This is what I've tried so far. I hope it also clarifies what I'm trying to do:
var kvps = getProps(); // returns IEnumerable<KeyValuePair<string,string>>
dynamic o = new ExpandoObject();
foreach (var kvp in kvps)
{
o.Add(kvp);
}
This is OK at compile time, but at runtime I get a YSOD stating 'System.Dynamic.ExpandoObject' does not contain a definition for 'Add' - I guess it works at compile time because o is dynamic, so the compiler can't know if a method .Add() has been added to it since it was instantiated. The odd thing is, that on the MSDN documenation page for ExpandoObject .Add() is listed as one of several "explicitly implemented interface methods".
It is not necessary for me to get this into a dynamic object - I just need to get something that has property names and values according to the keys and values of the key-value pairs.
Update: Well, this is embarrassing. Turns out this was something of an XY-problem too.
I'm trying to render this to JSON using the built-in features of ASP.NET MVC, by simply returning Json(data) in my controller. The answers all worked very well to do what I first asked, but when I pass this object as data I still don't get what I want:
// What I get:
[
{ Key: 'firstkey', Value: 'FirstValue' },
{ Key: 'secondKey', Value: 'secondValue' }
]
// What I want:
{ firstKey: 'FirstValue', secondKey: 'secondValue' }
Apparently, an ExpandoObject with the relevant properties added didn't cut it - it was cast to a dictionary before rendering...
You need to use the ExpandoObject as an IDictionary<string, object> while populating it:
var kvps = getProps(); // returns IEnumerable<KeyValuePair<string,string>>
IDictionary<string, object> o = new ExpandoObject();
foreach (var kvp in kvps)
{
// Or use Add(kvp.Key, kvp.Value), if you want
o[kvp.Key] = kvp.Value;
}
dynamic d = o;
// Now you can use the properties
ExpandoObject explicitly implements IDictionary<string, object> - so you need to cast it to one first:
var kvps = getProps();
dynamic o = new ExpandoObject();
var dict = o as IDictionary<string, object>;
foreach (var kvp in kvps)
{
dict.Add(kvp.Key, kvp.Value);
}
Now you can use o as you would expect:
var example = o.YourKey;
I'm trying to render this to JSON using the built-in features of ASP.NET MVC, by simply returning Json(data) in my controller.
Interesting.
To do that, you serialize a dictionary, not an ExpandoObject. MVC 3's JSON serializer already does that with a dictionary. All you have to do is convert your IEnumerable<KeyValuePair<string, object>> to a dictionary:
var kvps = getProps();
var dictionary = kvps.ToDictionary(k => k.Key, v => v.Value);
return Json(dictionary, JsonRequestBehavior.AllowGet); //take out allow get if you don't need it.
No dynamics required.
I think you have to cast your expando object to IDictionary and call Add(string, object)

Categories