I have the following Dictionary:
private Dictionary<string, double> averages = new Dictionary<string, double>();
Now I want to use reflection to add two additional values. I can retrieve the field info, but what else do I have to do?
FieldInfo field = ProjectInformation.SourceManager.GetType().GetField("averages");
if (field != null)
{
//what should be here?
}
MethodInfo mi = field.FieldType.GetMethodInfo("set_Item");
Object dict = field.GetValue(ProjectInformation.SourceManager);
mi.Invoke(dict, new object[] {"key", 0.0} );
If you need to get the field and values just for Unit Testing consider using Microsoft's PrivateObject
Its there so you can check the internal state of data members during unit testing if you need to, which appears to be what you are trying to do.
In your unit tests you can do the following:
MyObject obj = new MyObject();
PrivateObject privateAccessor = new PrivateObject(obj);
Dictionary<string, double> dict = privateAccessor.GetFieldOrProperty("averages") as Dictionary<string, double>;
Then you are free to get and set any values you need to from the Dictionary.
if(field != null)
{
field.GetValue(instance);
}
Related
I have a simple for loop but I want to convert it to Linq and return empty Dict. if object is null. I have not used it before. Can anyone help me out on this ?
private Dictionary<string, class1> getInfo(IEnumerable<class2> infos)
{
Dictionary<string, class1> trs = new();
if (infos is null)
return trs;
//This loop I want to convert to linq
for(class2 info in infos)
{
class1 tr = new()
{
bi = info.bi,
state = bi.State,
res = Enum.value;
};
trs.Add(info.value1, tr);
}
return trs;
}
You can use .ToDictionary() to create a dictionary from IEnumerable<class2>
Dictionary<string, class1> trs = infos
?.ToDictionary(key => Key.value1,
value => new class1() {
bi = value.bi,
state = bi.State,
res = Enum.value
}) ?? new Dictionary<string, class1>();
Free Advice : I highly recommend you to use proper naming conventions while declaring class and variables, this will make your code more readable and easy to understand
Is there a way to assign the key values of each object in a List to a Dictionary? I want to access that dictionary later to assign the values to properties of a class.
I fetch some values from a BD with inner joins, then I store the values in a list of objects:
IEnumerable<object> units = _unitDetailsQuery.Execute<object>(out totalRecords);
Each object has these properties:
Brand (string)
Model (string)
Code (string)
BranchId (int)
Then I create a Dictionary
IDictionary<string, object> props = new Dictionary<string, object>();
I've seen in another question something like this (i've adapted the snippet to my code):
BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance;
foreach (object unit in units)
{
props = unit.GetType().GetProperties(bindingAttr).ToDictionary
(
propInfo => propInfo.Name,
propInfo => propInfo.GetValue(unit, null)
);
}
But props gets no value after the assignment.
Internally the object is something like this:
So how do I get those values? Thanks in advance.
You can use this extension method, which will reflect over the object's public properties and put them into a dictionary.
public static class ObjectExtensionMethods
{
static public Dictionary<string, object> ToPropertyDictionary(this object o)
{
var d = new Dictionary<string, object>();
foreach (var p in o.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
d.Add(p.Name, p.GetValue(o));
}
return d;
}
}
You could use this on a list of objects like so:
var listOfDictionaries = listOfObjects.Select( o => o.ToPropertyDictionary() );
Giving credit to #John Wu, but since you said you wanted information to be editable, I think the extension method instead has to return string, System.Reflection.PropertyInfo instead. That way, properties can be updated and selected.
public static Dictionary<string, System.Reflection.PropertyInfo> ToPropertyDictionary(object o)
{
var d = new Dictionary<string, System.Reflection.PropertyInfo>();
foreach (var p in o.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
d.Add(p.Name, p);
}
return d;
}
This way, you can get/set the original object's properties. It could no longer be an extension method.
This way, you can edit the object like so. Let's say I have a random object named o with a variable named X that's an integer.
Then, I can get the dictionary.
var dict = ToPropertyDictionary(o);
Setting X with a value of 2 can be done with:
dict("X").SetValue(o, 2);
Getting X then would be done with:
dict("X").GetValue(o)
Say I have this object:
dynamic foo = new ExpandoObject();
foo.bar = "fizz";
foo.bang = "buzz";
How would I remove foo.bang for example?
I don't want to simply set the property's value to null--for my purposes I need to remove it altogether. Also, I realize that I could create a whole new ExpandoObject by drawing kv pairs from the first, but that would be pretty inefficient.
Cast the expando to IDictionary<string, object> and call Remove:
var dict = (IDictionary<string, object>)foo;
dict.Remove("bang");
You can treat the ExpandoObject as an IDictionary<string, object> instead, and then remove it that way:
IDictionary<string, object> map = foo;
map.Remove("Jar");
MSDN Example:
dynamic employee = new ExpandoObject();
employee.Name = "John Smith";
((IDictionary<String, Object>)employee).Remove("Name");
You can cast it as an IDictionary<string,object>, and then use the explicit Remove method.
IDictionary<string,object> temp = foo;
temp.Remove("bang");
Fairly new to programming. I just can't wrap my head around how to get this to work in reverse. I have a save method and an open method.
Save:
IDictionary<string, IDictionary<string, object>> pluginStates = new Dictionary<string, IDictionary<string, object>>();
signaller.RaiseSaveRequest(pluginStates); <--goes out and gets packed plugins
//loop through plugins to get values and types
//holds all of the plugin arrays
Dictionary<string, object> dictProjectState = new Dictionary<string, object>();
foreach (KeyValuePair<string,IDictionary<string,object>> plugin in pluginStates)
{
//holds jsonRepresented values
Dictionary<string, object> dictJsonRep = new Dictionary<string, object>();
//holds object types
Dictionary<string, object> dictObjRep = new Dictionary<string, object>();
object[] arrayDictHolder = new object[2]; //holds all of the dictionaries
string pluginKey = plugin.Key;
IDictionary<string, object> pluginValue = new Dictionary<string, object>();
pluginValue = plugin.Value;
foreach (KeyValuePair<string, object> element in pluginValue)
{
string jsonRepresentation = JsonConvert.SerializeObject(element);
object objType = element.Value.GetType().ToString();
dictJsonRep.Add(element.Key, jsonRepresentation);
dictObjRep.Add(element.Key, objType);
}
arrayDictHolder[0] = dictJsonRep;
arrayDictHolder[1] = dictObjRep;
dictProjectState.Add(pluginKey, arrayDictHolder);
}
JsonSerializer serializer = new JsonSerializer();
using (StreamWriter sw = new StreamWriter(strPathName))
using (JsonWriter writer = new JsonTextWriter(sw))
{
serializer.Serialize(writer, dictProjectState);
}
So, when someone saves, an event handler goes out and gets the packedState of each plugin, adds it to a dictionary pluginStates. I then go through each plugin in the pluginStates, adding the key, and json string version of the value to 1 dictionary and the key, object type to another dictionary, add those 2 dictionaries to an array and then pack up a dictionary that contains the pluginKey and the array for each plugin. Reasoning: when deserializing, I'm hitting problems going from JArray to type DataTable and other types that are within the dictionary that gets passed back to the plugin to unpack itself upon opening. I'm trying to figure out how to reverse this, so that when user opens project, I have the dictProjectState and need to bring it all the way back through the code to end up with 1 dictionary containing the plugins. How do I mirror this save in the open??
Thanks!
I believe when you deserialize in the open function, you should get an object that can be cast to Dictionary<string, object>.
The keys of this dictionary would be the names of the plugins in your final dictioary (pluginKey in yoru save method). The values should be the object[] arrayDictHolder objects. You can cast them to object[] and then get at the two values inside (dictJsonRep and dictObjRep in your save function).
Once those values are both cast to Dictionary<string, object>(), you can iterate through the KeyValuePairs in one of them, and use the key from those pairs to get at the value store in the other dictionary.
Code would be similar to the following:
var pluginStates = new Dictionary<string, IDictionary<string, object>>();
var dictProjectState = jsonSerializer.Deserialize(reader) as Dictionary<string, object>;
foreach(var projectStatePair in dictProjectState)
{
string pluginKey = projectStatePair.Key;
var pluginValues = new Dictionary<string, object>();
object[] arrayDictHolder = projectStatePair.Value as object[];
var dictJsonRep = arrayDictHolder[0] as Dictionary<string, object>;
var dictObjRep = arrayDictHolder[1] as Dictionary<string, object>;
foreach(var JsonRepPair in dictJsonRep)
{
string jsonRepresentation = JsonRepPair.Value;
// We know both dictionaries have the same keys, so
// get the objType for this JsonRepresentation
object objType = dictObjRep[JsonRepPair.Key];
// Since you're serializing objType to a string, you'll need
// to get the actual Type before calling DeserializeObject.
Type jsonType = System.Type.GetType(objType as string);
object value = JsonConvert.DeserializeObject( jsonRepresentation, jsonType );
pluginValues.Add( JsonRepPair.Key );
}
pluginStates.Add( pluginKey, pluginValues );
}
Note: You are currently setting objType to element.Value.GetType().ToString(); in your save function. You will either need to update save() to set it to element.Value.GetType(); or convert the type strings back to actual Types before trying to deserialize.
Note: I am not very familiar with the Json libraries. The above code is focused on creating your pluginStates dictionary out of the deserialized results. You will need to handle the creation of your JsonSerializer and make sure you close any streams after you've deserialized them. You may also need to tweak the actual deserialization calls to get the desired results.
Update: Added conversion of objType to actual System.Type object.
I was wondering what is the best way for getting the generic arguments that definine a dictionary at run time is.
Take for example:
Dictionary<string, object> dict;
How at runtime can I find out that the keys are strings?
I'm not sure if I understand your question correctly but I think you mean something like this:
Dictionary<string, object> dict = new Dictionary<string, object>();
// ...
var args = dict.GetType().GetGenericArguments();
// args[0] will be typeof(string)
Here's an NUnit test to demonstrate Mehrdad's answer, and with a dictionary containing integers as keys, and strings as values:
[Test]
public void testGetPhysicalTypeForGenericDictionary()
{
IDictionary<int, string> myDictionary = new Dictionary<int, string>();
Type [] myTypes = myDictionary.GetType().GetGenericArguments();
Assert.AreEqual(2, myTypes.Length);
var varTypes = myDictionary.GetType().GetGenericArguments();
Assert.AreEqual("Int32", varTypes[0].Name);
Assert.AreEqual("System.Int32", varTypes[0].FullName);
Assert.AreEqual("String", varTypes[1].Name);
Assert.AreEqual("System.String", varTypes[1].FullName);
}