Getting the property name that a value came from - c#

I would like to know how to get the name of the property that a method parameter value came from. The code snippet below shows what I want to do:
Person peep = new Person();
Dictionary<object, string> mapping = new Dictionary<object, string>();
mapping[peep.FirstName] = "Name";
Dictionary<string, string> propertyToStringMapping = Convert(mapping);
if (mapping[peep.FirstName] == propertyToStringMapping["FirstName"])
Console.WriteLine("This is my desired result");
private Dictionary<string, string> Convert(Dictionary<object, string> mapping)
{
Dictionary<string, string> stringMapping = new Dictionary<string, string>();
foreach (KeyValuePair<object, string> kvp in mapping)
{
//propertyName should eqal "FirstName"
string propertyName = kvp.Key??????
stringMapping[propertyName] = kvp.Value;
}
return stringMapping;
}

You are not able to do so in this way, since the way it works is that C# evaluates the value of FirstName property by calling its get accessor and passes the value of that to the indexer of the dictionary. Therefore, the way you found out FirstName value is completely lost. Just like the way you evaluate 2 + 2.
If you write, "x = 2 + 2", x will have the value 4 but there will be no way to tell if it was 3 + 1 or 2 + 2 or 5 + (-1) or ... that evaluated to 4.

I think ultimately you will need to store either the PropertyInfo object associated with the property, or the string representation of the property name in you mapping object. The syntax you have:
mapping[peep.FirstName] = "Name";
Would create an entry in the dictionary with a key value equal to the value of the peep.FirstName property, and the Value equal to "Name".
If you store the property name as a string like:
mapping["FirstName"] = "Name";
You could then use reflection to get the "FirstName" property of your object. You would have to pass the "peep" object into the Convert function, however. This seems to be somewhat opposite of what you are wanting to do.
You may also be able to get crazy with Expressions and do something like:
var mapping = new Dictionary<Expression<Action<T>>,string>();
mapping[ p => p.FirstName ] = "Name";
Then in your Convert function you could examine the expression. It would look something like:
private Dictionary<string,string> Convert(Dictionary<Expression<Action<T>>,string> mapping)
{
var result = new Dictionary<string,string>();
foreach(var item in mapping)
{
LambdaExpression ex = item.Key as LambdaExpression;
string propertyName = ((MemberExpression)ex.Body).Member.Name;
string propertyValue = item.Value;
result.Add(propertyName,proeprtyValue);
}
return result;
}
This is more or less off the top of my head, so I may have the expression types off a bit. If there are issues with this implementation let me know and I will see if I can work out a functional example.

I don't know much about C#, but I suppose peep is an enum? As for Java, you could do:
String propertyName = kvp.key.toString()
Maybe there's something similar in C#?
And even if peep isn't a enum: I see no reason why the key should be an arbitrary object? So maybe the solution is exactly to use an enum as type of the key?
Also, I don't know what you're trying to do but usually, I'd not recommend you to convert the enum key to a string. What can you do with a string what you can't do, too, with an enum?

Related

How to use Linq and lambda expressions on a Dictionary<string, List<T>> to a specify its order based on Key

So I have a Dictionary with string keys, and the value is a List of objects. Each object in each List has a property value which is equal to that List's associated key. In other words, the Dictionary is grouping objects by property value via the key. For example, let's say we have,
Dictionary<string, List<Animal>> GroupedByClass = new Dictionary<string, Animal>();
Where Animal is an object which contains a string property named "ClassType" which has valid options of "Mammal", "Reptile", or "Amphibian", etc.
The Animal class could also have string property named "Species" which more uniquely defines each object in the Dictionary.
A pseudocode description of the contents of the Dictionary could be:
<"Mammal", List<Animal>>
where the Animals in the list have Species "Dog", "Cat"
<"Reptile", List>
where the Animals in the list have Species "Snake", "Lizard", and "Turtle"
<"Amphibian", List>
where the Animals in the list have Species "Salamander" and "Frog"
I want to rearrange this Dictionary by the key value such that the values with a key of "Reptile" are first, then "Amphibian", and then finally "Mammal". Note that I do not want to sort this based on alphabetical order, I want to specify my own order.
I know I could solve this problem by simply iterating through the Dictionary a few times, extracting only the items with the right key. For example, I could do it like this,
Dictionary<string, List<Animal>> temp = new Dictionary<string, List<Animal>>();
foreach(KeyValuePair<string, List<Animal>> item in GroupedByClass)
{
if(item.Key == "Reptile")
{
temp.Add(item.Key, item.Value);
}
}
foreach(KeyValuePair<string, List<Animal>> item in GroupedByClass)
{
if(item.Key == "Amphibian")
{
temp.Add(item.Key, item.Value);
}
}
foreach(KeyValuePair<string, List<Animal>> item in GroupedByClass)
{
if(item.Key == "Mammal")
{
temp.Add(item.Key, item.Value);
}
}
return temp;
However, this seems inelegant, and I was wondering if there was a better answer for this problem using Linq queries and lambda expressions.
This should be close (with some syntax errors):
var order = new [] {"Reptile","Amphibian","Mammal"};
var elems = dict.OrderBy(x=>order.IndexOf(x.Key));
if you want to flatten the results, then you can use SelectMany:
var order = new [] {"Reptile","Amphibian","Mammal"};
var elems = dict.SelectMany(x=>x).OrderBy(x=>order.IndexOf(x.Species));
Dictionary<string, List<Animal>> temp = new Dictionary<string,List<Animal>>();
(new List<string>() {"Reptile","Amphibian","Mammal"}).ForEach(x => temp.Add(x, GroupedByClass[x]));
You could define an enumeration and have it be your defining order.
enum Animal : int
{
Reptile = 0,
Amphibian = 1,
Mammal = 2
}
Note, since you have simple strings this works and is straight forward. If however you end up with strings that have spaces you can use the DescriptionAttribute of the enumeration and go between it and the actual enumeration.
Enumeration with Display String
By using an enumeration over the string you can do many things, but of course order by it using the integers you assiged.

How to get value from dictionary without knowing key?

I want to get value from dictionary but i don't know key(Because dynamic generate dictionary from database) how can i get dictionary value.
If you some idea share me ...
For Example my database string value like
string jsonString = " "FB": "[{\"title\":\"sheet1\",\"rows\":[{\"height\":\"undefined\",\"columns\":[{\"value\":\"Cover Group \"},{\"value\":\"Sample Variable\"},{\"value\":\"Coverpoint Name\"},{\"value\":\"Crossed cover points\"},{\"value\":\"Coverpoint Comment\"},{\"value\":\"Bin Type\"},{\"value\":\"Bin Id\"},{\"value\":\"Sample Value\"},{\"value\":\"Expected Bin Count\"},{\"value\":\"Set Max Bin\"},{\"value\":\"Not Used\"}]},{\"height\":\"undefined\",\"columns\":[{\"value\":\"allCg,allSi\"},{\"value\":\"exSingle\"},{\"value\":\"exSingle\"},{},{\"value\":\"Example for single bin\"},{\"value\":\"single\"},{\"value\":\"valZero\"},{\"value\":\"1'b0\"},{\"formula\":\"1\",\"value\":1},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{},{},{},{},{\"value\":\"single\"},{\"value\":\"valOne\"},{\"value\":\"1'b1\"},{\"formula\":\"1\",\"value\":1},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{\"value\":\"ex1Bus[3:0]\"},{\"value\":\"exMulti\"},{},{\"value\":\"Example for multibin\"},{\"value\":\"multi\"},{},{\"value\":\"[0:15]\"},{\"formula\":\"16\",\"value\":16},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{},{\"value\":\"exCross\"},{\"value\":\"exSingle,exMulti\"},{\"value\":\"Example for cross\"},{\"value\":\"Implicit\"},{},{},{\"formula\":\"32\",\"value\":32},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{\"value\":\"ex2Bus[15:0]\"},{\"value\":\"exWildcard\"},{},{\"value\":\"example for wildcard\"},{\"value\":\"wildcard\"},{\"value\":\"ex_wildcard\"},{\"value\":\"16'bxxxxxxxxxxxxxx1\"},{\"formula\":\"1\",\"value\":1},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{\"value\":\"ex3Bus[4:0]\"},{\"value\":\"exImplicit\"},{},{\"value\":\"example for implicit & set max bin\"},{\"value\":\"Implicit\"},{},{},{\"formula\":\"8\",\"value\":8},{\"formula\":\"8\",\"value\":8},{}]},{\"height\":\"undefined\",\"columns\":[{},{\"value\":\"ex4Bus[3:0]\"},{\"value\":\"ex4Bus\"},{},{\"value\":\"setup for ignore example\"},{\"value\":\"multi\"},{},{\"value\":\"[0:15]\"},{\"formula\":\"16\",\"value\":16},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{},{\"value\":\"exIgnore\"},{\"value\":\"exSingle,ex4Bus\"},{\"value\":\"example for ignore\"},{\"value\":\"ignore\"},{},{\"value\":\"ex4Bus([12:15])\"},{\"formula\":\"24\",\"value\":24},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{\"value\":\"ex5Bus[3:0]\"},{\"value\":\"exIllegal\"},{},{\"value\":\"example for illegal\"},{\"value\":\"illegal\"},{},{\"value\":\"[12:15]\"},{\"formula\":\"16\",\"value\":16},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{},{},{},{},{},{},{},{},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{},{},{},{},{},{},{},{},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{},{},{},{},{},{},{},{},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{},{},{},{},{},{},{},{},{},{}]},{\"height\":\"undefined\",\"columns\":[{},{},{},{},{},{},{},{},{},{},{}]}],\"metadata\":{\"widths\":[\"200\",\"200\",\"200\",\"200\",\"200\",\"200\",\"200\",\"200\",\"200\",\"200\",\"200\"],\"frozenAt\":{\"row\":0,\"col\":0}}}]""
FB is dynamic key and after it's value title all value i need
If you don't have the key, but have the value and trying to get hold of the key, you can do this:
Dictionary<string, string> testData = new Dictionary<string, string>();
testData.Add("name", "Latheesan");
testData.Add("age", "26");
KeyValuePair<string, string> searchResult
= testData.FirstOrDefault(s => s.Value == "Latheesan");
string key = searchResult.Key; // returns "name" here
To get a sequence of all the Key/Value pairs where the value matches a target:
var dict = new Dictionary<string, int>
{
{"One", 1},
{"Two", 2},
{"Another One", 1},
{"Three", 3},
{"Yet Another One", 1}
};
int target = 1; // For example.
var matches = dict.Where(item => item.Value == target);
foreach (var kvp in matches)
Console.WriteLine("Key = " + kvp.Key);
The sample data you posted isn't a flat key-value dictionary. It contains embedded dictionaries - the base dictionary contains a title and a rows, which in turn consists of height and columns and so on, and at some point are key-value pairs who keys are, confusingly, named 'value'. Are you asking how to parse this data structure to get all the values whose key is value?
What you first need to do, since this appears to be a JSON-formatted entry, is parse the JSON into a .NET data structure, using libraries like JSON.NET or System.Web.Helpers.Json. These libraries will convert the JSON string into a hierarchy of dictionaries, all of them implementing IEnumerable, so you can iterate over it, more or less like this (this is not compilable code, just a demonstration!):
public void Main()
{
var jsonObject = Json.Decode(FB); // FB is your JSON string.
var values = new List<string>();
FindValues(jsonObject);
}
public void FindValues(jsonObject, values)
{
foreach (var child in jsonObject)
{
if (child.key == 'value')
{
values.Add(child.value);
}
// Recursively call FindValues on child objects.
FindValues(child, values);
}
}
This C#-ish pseudo-code shows you how to go over a dictionary, then optionally drill down deeper into internal dictionaries.
This code use for get value from dictionary value without knowing key and value..
var json = Newtonsoft.Json.JsonConvert.SerializeObject(jsonString );
var javSer = new JavaScriptSerializer();
var dfi = javSer.Deserialize<Dictionary<string, string>>(json);
string dataString= dfi.Values.First();
How can you possibly know which value you need if you don't have the key?
A Dictionary in .NET does contain a Keys and Values collection, so if you are only interested in the values, you can use that.

Collection Like Dictionary<K, V> That allows Value Change

I understand why there isn't a method built in to do this, however I want a collection object that will allow Value change possibly during Enumeration.
Imagine the following:
Dictionary<string, List<string>> test = new Dictionary<string, List<string>> {{"key", null}};
Lets say I have 20 of these within a class which implements IEnumberable
I'd like to use lambda or a simple foreach to iterate through the class and find the object matching a key, then store my List<T> with the Value parameter.
You might be looking for a collection called multimap. See here for my implementation of it.
As you have discovered you can't change a DictionaryEntry through the Value property - you have to go through the Item accessor using the Key.
One option is to turn your Where results to an array then loop to get the matching Keys:
Dictionary<string, List<string>> test = new Dictionary<string, List<string>>
{{"key", null}};
test.Add("newKey",null);
var matches = test.Where(di => di.Key == "key").ToArray();
foreach(var di in matches) {
test[di.Key] = new List<string> {"one","two"};
You can just use this to modify a value in a dictionary:
public static void ChangeValue(string indexKey,List<string> newValue)
{
if (test.ContainsKey(indexKey))
keysDictionary[indexKey] = newValue;
}
You could avoid using an enumerator altogether, e.g.
var data = myEnumerable.ToArray();
for(var i = 0; i < data.Length; i++) {
// here you can manipulate data[i] to your heart's content
}

How to use TreeView.Tag = object?

Something like this:
Dictionary<int, string> myData = new Dictionary<int, string>();
myData.Add(1, "England");
myData.Add(2, "Canada");
myData.Add(3, "Australia");
myTreeView.Node[0].Tag = myData;
Then I want to get this object, how should I do it ?
Like:
string str = new string();
str = myTreeView.Node[0].Tag[2]; // "str" should be equal to "Canada"
myTreeView.Node[0].Tag[1] = "Spain";
str = myTreeView.Node[0].Tag[1]; // now "str" is equal to "Spain"
Second question - what will return this expression:
Dictionary<int, string> myData = new Dictionary<int, string>();
myData.Add(1, "England");
myData.Add(2, "Canada");
myData.Add(3, "Australia");
string str1 = new string();
str = myData[4]; // there isn't such a key as 4
Exception or null ?
Control.Tag is typed as object so you'll need to cast it to access it as a Dictionary<int, string>:
Dictionary<int, string> dict = (Dictionary<int, string>)myTreeView.Node[0].Tag;
string str = dict[2];
And similarly to set a value:
var dict = (Dictionary<int, string>)myTreeView.Node[0].Tag;
dict[1] = "Spain";
If you try to access a non-existent key, a KeyNotFoundException will be thrown. You can check if the dictionary contains a given key using TryGetValue or ContainsKey:
if(dict.ContainsKey(key))
{
var value = dict[key];
}
else
{
}
TryGetValue does the lookup and sets the given variable to the value (it it exists) in a single call, so is usually preferred.
string value;
if(dict.TryGetValue(key, out value))
{
//use value
}
else { ... }
Exception or null ?
Well, you could just try it out yourself or read the documentation (it throws an exception).
Also, your code will not compile as posted. Tag is a way to associate arbitrary data with an object. As a result, its type is object, so you will need to cast it before using it as you do.
If your code ever becomes unwieldy due to overuse of the Tag property I would suggest creating your own node type which inherits from the default TreeNode (or whatever it is) and populating your tree view with that type of object instead.
The tightest means for addressing the properties of a node tag is:
((TagType)node_identity.Tag).TagProperty = value;
Thus the tag properties of the parent node can be addressed so:
((TagType)node_identity.Parent.Tag).TagProperty = value;
The tag properties of a child node can be addressed so:
((TagType)node_identity.Nodes[index_of_child].Tag).TagProperty = value;
And as each Nodes[index_identifier] resolves to a node, the tag properties of more remote child nodes can be addressed so:
((TagType)node_identity.Nodes[index_of_child].Nodes[index_of_further_child].Tag).TagProperty = value;
Etc.
As far as the assumable objects of Tagging your dictionary are concerned... assuming your purposes require the same integer-string associations everywhere, I would instead simply store the integer key value to your Tag field, and pull the associated string from perhaps a global List<string> DictionaryStrings object. Then you could store only the integer index value to your Tags; and only the string values to your List<string>.
You would then read your Tag values as follows:
((int)node_identity.Tag)
Given these assumptions, you would instead populate your infrastructure so:
List<string> DictionaryStrings = new List<string>;
DictionaryStrings.Add("Canada"); // etc.
Then you would read the tag to pull your DictionaryString from the index value stored to your Tags as follows:
string DictionaryString = DictionaryStrings[((int)node_identity.Tag)];
Your error message is a consequence of addressing a prospective member of your dictionary which you have not yet added (at that execution point) to your dictionary. Fully populate the List or dictionary first; then only address valid indexes belonging to the List/dictionary.

C# properties as array notation

Using JavaScript it's possible to access an object using the dot notation or array notation.
var myArray = {e1:"elem1",e2:"elem2",e3:"elem3",e4:"elem4"};
var val1 = myArray["e1"];
var val2 = myArray.e1;
Is it possible to accomplish this using C#?
This is what I have attempted:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection frmVals)
{
string value;
Owner owner = new Owner();
foreach (var key in frmVals.AllKeys)
{
value = frmVals[key];
owner[key] = value;
}
}
While there is no way to do this exactly with C#. You could change your code in several ways that may accomplish your goal. First, you could use a Dictionary like this:
var something = new Dictionary<string, object>() {
{ "property", "value"},
{ "property1", 1}
};
foreach (var keyVal in something) {
var property = keyVal.Key;
var propertyValue = keyVal.Value;
}
Another option would be to do it dynamically:
dynamic somethingDyn = new System.Dynamic.ExpandoObject();
somethingDyn.property = "value";
somethingDyn.property1 = 1;
var somethingDynDict = (IDictionary<string, object>)somethingDyn;
var propValue = somethingDyn["property"];
foreach (var keyVal in somethingDynDict) {
var property = keyVal.Key;
var propertyValue = keyVal.Value;
}
If you need to iterate through properties on a strongly typed object you could use reflection:
var owner = new Metis.Domain.User();
var properties = owner.GetType().GetProperties();
foreach (var prop in properties) {
object value = prop.GetValue(owner, null);
}
I wouldn't recommend this, but you could put an indexer in your class, accepting a string, then use reflection to read that property. Something like:
public object this[string key]
{
get
{
var prop = typeof(ThisClassName).GetProperty(key);
if (prop != null)
{
return prop.GetValue(this, null);
}
return null;
}
set
{
var prop = typeof(ThisClassName).GetProperty(key);
if (prop != null)
{
prop.SetValue(this, value, null);
}
}
}
Javascript array notation is not something you can use in C#.
You need to use dot notation to access members of an object.
You will need to access each value directly and assign it:
owner.key = frmVals[key];
owner.key2 = frmVals[key2];
There are workarounds - using dictionaries, dynamic objects or even reflection, but the scenario is not a directly supported by C#.
There is no syntactic equivalent possible in C# but there are some ways to approximate the same feature.
You could mimic the indexer type access using a Dictionary but then you'd lose the property-style access. For property-style access, you could do something similar in C# by using an anonymous type, as in:
var myType = new { e1="elem1",e2="elem2",e3="elem3",e4="elem4"};
var val1 = myType.e1;
However, that doesn't create an array or allow array type access and it doesn't allow for modifications to the type after creation.
To get a closer approximation to the JavaScript feature, you may be able to use ExpandoObject to mimic this a little more closely, or you could implement something yourself.
For that, you'd need a class that has a constructor to auto-generate properties from the passed in array and exposes an indexer, which in turn uses reflection to find the named property.
Initialization of this type would be something like:
var myType = new MyType(new[]{
{"e1", "elem1"},
{"e2", "elem2"},
{"e3", "elem3"},
{"e4", "elem4"}});
This assumes there is a sub-type for each element definition (possibly using Tuple or KeyValuePair. The constructor would then be taking an IEnumerable<T> of that type.
Yes, it's possible.
There are two possibilities:
1) The list of keys and values is dynamic.
The array notation is provided by e.g. System.Collections.Generic.Dictionary<string, blah>
The member access notation can be provided through DLR magic and the dynamic keyword.
2) The list of keys and values is static.
Member access notation is already provided by the C# compiler.
Array notation can be had using Reflection (hopefully with a cache to improve performance).
In the static case, member access notation is MUCH faster. In the dynamic case, array notation will be a little faster.

Categories

Resources