I've a problem with updating a dictionary
I also have read many topics about this saying all the same (e.g. Link)
ExampleDict[key] = value;
I was trying this to my own code:
Model:
public Dictionary<int, string> Info { get; set; }
public Dictionary<int, string> GetInfo(int id)
{
Info = new Dictionary<int, string>();
var game = db.Games.Find(id);
var playerOne = db.Players.Find(game.PlayerOneId);
var playerTwo = db.Players.Find(game.PlayerTwoId);
var PlayerOneName = playerOne.Nickname;
var PlayerTwoName = playerTwo.Nickname;
int scoreOne = CountScorePlayerOne();
int scoreTwo = CountScorePlayerTwo();
// old aproach:
Info.Add(scoreOne, PlayerOneName);
Info.Add(scoreTwo, PlayerTwoName);
//new approach
Info[key] = scoreOne;
return Info;
}
Error
The name 'key' does not exist in the current context
Note: I'm a student and this is for a school project.
Any ideas on what I am doing wrong?
Solved through the code sample from Jon Senchyna, Thank you!
It appears that you are never declaring the variable key. You probably did not mean to use "key" in the "new approach" line.
In addition, I believe your Dictionary is backwards, as it looks like the player name should be the key, not their score. The way you are currently declaring it (Dictionary<int, string>), you are creating a dictionary whose keys are int (score?) and whose values are string (name?).
Here are my suggested edits:
// Corrected dictionary definitions
public Dictionary<string, int> Info { get; set; }
public Dictionary<string, int> GetInfo(int id)
{
// You may want to use a local variable here instead
Info = new Dictionary<string, int>();
...
Info[PlayerOneName] = scoreOne;
Info[PlayerTwoName] = scoreTwo;
return Info;
}
Here are some useful links for learning more about using the Dictionary class (and C# in general if you browse around a bit):
MSDN
DotNetPearls
In the example link in your question there's the method:
public static void SafeDictionaryAdd(Dictionary<string, object> dict, string key, object view)
Which has a string key as an argument. You need to define that key, too.
Related
What is the proper syntax to obtain a dictionary key value pair when using trace points?
With a property like the following
public Dictionary<string, decimal> SomeDictionary { get; set; }
I am trying to set a break point with actions on the setter method to trace all incoming values. I've tried the following but none of them work.
{value} 'this gives me a count of how many items are in the dictionary
{value.Value} 'throws an exception, 'Value' doesn't exist
{value[Value]} 'the name 'Value' does not exist in the current context
Based on your SomeDictionary:
public class Example
{
public Dictionary<string, decimal> SomeDictionary { get; set; }
public Example()
{
SomeDictionary = new Dictionary<string, decimal>();
string key = "key";
SomeDictionary[key] = 10.0M;
}
}
static void Main(string[] args)
{
var example = new Example();
Console.ReadKey();
}
If we put a tracepoint at the end of the constructor after the dictionary is defined and the key is added - Tracepoint action:
SomeDictionary: {SomeDictionary}; SomeDictionary[key]: {SomeDictionary[key]}
We can inspect the dictionary - Output:
SomeDictionary: Count = 1; SomeDictionary[key]: 10.0
You can reference the dictionary by using
{ map["key1"] }
or using variable to access the keyvalue pair.
In Unity3D I am trying to loop through all the components on an object and get their variables and values. This is the code that keeps throwing the exception:
componentvariables = new ComponentVars[component.GetType().GetFields().Length];
int x = 0;
//Get all variables in component
foreach(FieldInfo f in component.GetType().GetFields()){
componentvariables[x]=new ComponentVars();
componentvariables[x].Vars.Add(f.Name,f.GetValue(component).ToString());
x++;
}
The ComponentVars class is
public class ComponentVars{
public Dictionary<string, string> Vars{get;set;}
}
Yes I know it is very simple and I could just use an array of dictionaries but I plan on adding more to it later.
The part that keeps throwing the error is
componentvariables[x].Vars.Add(f.Name,f.GetValue(component).ToString());
I usually see these where a variable is not initialized but I have tried initializing it (as seen in the code above) and I still continue to get a NullRefEx.
Can anyone see what I am doing wrong here?
Make sure you initialize your Vars dictionary before you try to add a value to it:
foreach(FieldInfo f in component.GetType().GetFields()){
componentvariables[x] = new ComponentVars();
componentvariables[x].Vars = new Dictionary<string, string>();
componentvariables[x].Vars.Add(f.Name, f.GetValue(component).ToString());
x++;
}
Or even better, initialize it in the class:
public class ComponentVars{
public Dictionary<string, string> Vars { get; private set; }
public ComponentVars()
{
this.Vars = new Dictionary<string, string>();
}
}
I've read few posts, and I'm still having troubles with adding properties to a class in runtime. It should be simple, because I have a class like this:
public class MyClass
{
String Template;
String Term;
}
During runtime, I have to add few attributes, like Phone, Email (it depends...).
Could someone please explain me how to add these properties during class initialization?
Srecko
I don't think adding a property is the right thing to do here.
The attributes like "Email" or "Phone" are just some additional pairs of a key and a value. You could use a Dictionary, but that would prevent you from using a key more than once (more than one email address for a contact for example). So you could just as well use a List<KeyValuePair<string, string>>. Like that:
public class MyClass
{
String Template;
String Term;
public List<KeyValuePair<string, string>> Attributes { get; private set; }
public MyClass() {
Attributes = new List<KeyValuePair<string, string>();
}
public void AddAttribute(string key, string value) {
Attributes.Add(new KeyValuePair<string, string>(key, value));
}
}
// to be used like this:
MyClass instance = new MyClass();
instance.AddAttribute("Email", "test#example.com");
instance.AddAttribute("Phone", "555-1234");
If you have c# 4.0 you can use the Expando object.
for earlier versions of c#, the generally accepted way of doing this is to create a "property bag" i.e. a collection (or dictionary) of key value pairs
dynamic foo = new ExpandoObject();
foo.Bar = "test";
you could add an dictionary with for your Key/Value-Pairs.
Then if you add your attributes you just add Key = Attributename, Value = YourValue to the dictionary.
Reading is as easy - just get the Value to the Key = Attributename from your dictionary.
I am using a Dynamic dictionary in C#. The problem I am facing is the behavior of TryGetMember which I am overriding in the dynamic dictionary class.
Here's the code of dynamic dictionary.
class DynamicDictionary<TValue> : DynamicObject
{
private IDictionary<string, TValue> m_dictionary;
public DynamicDictionary(IDictionary<string, TValue> a_dictionary)
{
m_dictionary = a_dictionary;
}
public override bool TryGetMember(GetMemberBinder a_binder, out object a_result)
{
bool returnValue = false;
var key = a_binder.Name;
if (m_dictionary.ContainsKey(key))
{
a_result = m_dictionary[key];
returnValue = true;
}
else
a_result = null;
return returnValue;
}
}
Here, TryGetMember will be called at runtime whenever we refer some key from outside, but it's strange that binder's Name member which always gives the key what we refer from outside, it always resolves the key name written as characters of alphabets.
e.g. if the object of DynamicDictionary made as:
Dictionary<string,List<String>> dictionaryOfStringVsListOfStrings;
//here listOfStrings some strings list already populated with strings
dictionaryOfStringVsListOfStrings.Add("Test", listOfStrings);
dynamic dynamicDictionary_01 = new
DynamicDictionary<List<String>(dictionaryOfStringVsListOfStrings);
string somekey = "Test";
//will be resolve at runtime
List<String> listOfStringsAsValue = dynamicDictionary_01.somekey
Now what happens here is "somekey" will become the value of a_binder (i.e a_binder.Name="somekey"). It should be resolved as a_binder.Name = "Test" and then from the dynamic dictionary it will locate listOfStrings against this key (i.e. actually "Test" but it resolves not the value but actual variable name as key).
Is there a way around this?
The point of dynamic typing is to make the member names themselves get resolved from the source code member access.
Dynamic typing is working exactly as it's meant to here - it's not designed to retrieve the value of the variable and use that as the member name - it's designed to use the member name you used in your source code (i.e. "somekey").
It sounds like you really don't need dynamic typing at all here - just use Dictionary<string,List<String>> as normal:
List<String> listOfStringsAsValue = dictionary[somekey];
EDIT: It sounds like you actually want to encapsulate a dictionary like this:
public class Foo // TODO: Come up with an appropriate name :)
{
private readonly Dictionary<string, List<string>> dictionary =
new Dictionary<string, List<string>>();
public List<string> this[string key]
{
get
{
List<string> list;
if (!dictionary.TryGetValue(key, out list))
{
list = new List<string>();
dictionary[key] = list;
}
return list;
}
}
}
Then you can do:
foo["first"].Add("value 1");
foo["second"].Add("value 2")
foo["first"].Add("value 1.1");
If you want to be able to attempt to fetch a list without creating a new one if it doesn't exist, you could add a method to do that.
It really doesn't sound like you need DynamicObject here.
I have a employee object as shown below
class emp
{
public int EmpID { get; set; }
public string EmpName { get; set; }
public int deptID { get; set; }
}
I need to create a mapping either in this class or a different class to map the properties with column name of my SQL
for eg. EmpdID="employeeID"
EmpName="EmployeeName"
deptID="DepartmentID"
When from my asp.net page when I create the employee class and pass it to a function:
for eg: emp e=new emp();
e.EmpID=1;
e.EmpName="tommy";
e.deptID=10;
When the emp object is populated and passed to the buildValues function it should return array of ComumnName(e.g.employeeID):Value(e.g.1),EmployeeName:tommy,DepartmentID:10)
string[] values=buildValues(emp);
public string[] buildValues(emp e)
{
string[] values=null;
return values;
}
I have 2 questions:
1. Where do I specify the mappings
2. How do I use the mappings in my buildValues function shown above and build the values string array.
I would really appreciate if you can help me with this
You need to use Reflection.
Specifically, you need to loop over typeof(Employee).GetProperties().
This is a solved problem. Do some research on ORM's and have a look at this SO question: .Net ORM that works well with MySQL
First of all, (as it was already said) it's best to leave this kind of mappings to an ORM tool, and just forget about them. However, ORM tools tend to be too "maternal" in protecting you from the gory details of data access and such, so it can be complicated to extend them, or change their behaviour.
That said, you could create a special class (Mappings) that would hold all mapping code. The mappings themselves are best kept in a dictionary, something like this:
static class Mappings
{
private static Dictionary<Type, Dictionary<string, string>> TypeMappings;
private static Dictionary<string, string> EmployeeMapping;
//... other mapped classes
static Mappings()
{
TypeMappings = new Dictionary<Type, Dictionary<string, string>>();
EmployeeMapping = new Dictionary<string, string>();
EmployeeMapping.Add("EmpID", "EmployeeID");
EmployeeMapping.Add("EmpName", "EmployeeName");
EmployeeMapping.Add("DeptID", "DepartmentID");
TypeMappings.Add(typeof(Employee),EmployeeMapping);
//... other mapped classes
}
public static string[] BuildValues<T>(T item)
{
if (!TypeMappings.ContainsKey(typeof(T)))
throw new Exception("wrong call");
Dictionary<string, string> mapping = TypeMappings[typeof(T)];
List<string> results = new List<string>();
foreach (var keyValuePair in mapping)
{
string propName = keyValuePair.Key;
string dbName = keyValuePair.Value;
PropertyInfo pi = typeof(T).GetProperty(propName);
object propValue = pi.GetValue(item, null);
results.Add(string.Format("{0}:{1}", dbName, propValue));
}
return results.ToArray();
}
}
Here, the TypeMappings is a dictionary of all mapped classes, whose mappings in turn are in propertyName - databaseName dictionaries.
The BuildValues method, takes those names, reflects the values, and build a results string.