I have not yet noticed that James Newton King wrote or spoke about what JToken is. I have made the incorrect assumption that it somehow holds a reference to JObject. This is not the case as the these LINQPad statements demonstrate:
var json = #"
{
""item"": {
""foo"": ""4"",
""bar"": ""42""
}
}
";
var jO = JObject.Parse(json);
var jToken = jO["item"]["foo"];
jToken = "5";
jO.ToString().Dump("jO");
jToken.Dump("jToken");
The output:
jO
{
"item": {
"foo": "4",
"bar": "42"
}
}
jToken
5
Should not jO["item"]["foo"] == 5?
First, let's talk about what a JToken is.
JToken is the abstract base class for JObject, JArray, JProperty and JValue.
JObject is a collection of JProperty objects. A JObject cannot hold any other kind of JToken.
JProperty is a name-value pair. The name is always a string, and the value can be any kind of JToken except another JProperty.
JArray is an array of JToken objects of any kind except JProperty.
JValue represents a JSON primitive value. It can contain a string, number, boolean, date or null. Note that JValue is a reference type like all other JTokens.
The above classes are intended to model the JSON spec.
Now let's talk about what you're doing and where you're getting confused.
In your code, you are first creating a JObject. The JObject contains one JProperty called item. The value of item is another JObject which contains two JProperties, called foo and bar. The values of these JProperties are both JValues containing strings (4 and 42, respectively).
Next, you use the JToken indexer syntax to get a reference to the value of the foo JProperty (a JValue which contains the string value 4) and assign that reference to your jToken variable. Note the declared type of this variable is JToken, even though the actual type of the value here is in fact JValue. (You can see this if you do jToken.GetType().Name.Dump("jToken type") )
With me so far?
OK, here is where I think you are getting confused. JToken provides implicit and explicit conversions which allow it to be assigned from or cast to various .NET primitives. If you do jToken = "5" that really means the same thing as jToken = new JValue("5"). So what you have done is to replace the reference that your jToken variable had (to the JValue containing 4) with a new reference to a different JValue containing 5. This obviously will have no effect on the original JObject.
If you are trying to modify the value of the original JValue, you need to cast your jToken to JValue and then use the Value setter to set it.
((JValue)jToken).Value = "5";
Fiddle: https://dotnetfiddle.net/StIGxM
Actually JToken has a reference to its parent (check Parent property).
Back to your example - in this line jToken = "5"; you are creating new JToken (to be more specific, string is implicitly converted to JValue). Basically it is the same as jToken = new JValue("5"); So variable jToken is now pointing to brand new JValue. This explains why the change is not reflected in original JObject.
To fix your example use: ((JValue)jToken).Value = "5";
Related
Is there a way to check if your session variable contains something... Just like a list has a method "Contains". Is there something similar to that? Some method or something?
Hi you can try casting your session so it can have a type for example
var listofperson = Session["ListofPerson"] as List<string>;
var hasGeorge = listofperson.Contains("George");
When you retrieve items from Session, they are of type System.Object. This means that you don't get any of the actual methods available for the object's real type. You can do so by casting it to the correct type. In this case, it sounds like you're storing a List<string>. So we can use the as operator. If the object is not of that type or was null to begin with, myList will null. Otherwise it will be of the type you specify.
List<string> myList = Session["myKey"] as List<string>();
if(myList == null)
{
//either Session["myKey"] was null or the object wasn't a List<string>
}
else
{
if(myList.Contains("fuzzy puppies"))
{
//your list contains fuzzy puppies
}
else
{
//your list doesn't contain fuzzy puppies
}
}
Calling .ToString() on an object gives you different results based on the object type. The default behavior is to print out the type of the object. But types can override this behavior. For example, calling .ToString() on a string just gives you the string itself. Calling .ToString() on an object that represents some XML might give you the XML as a string. Since List<string> doesn't override the default behavior of System.Object.ToString(), it just prints out "System.Collections.Generic.List`1[System.String]"
First, check if Session["yoursession_var"] is null. Then cast to List(). Then use Exists(), as described here: how to use Exist in List<string> in C#
According to Microsoft's documentation, FieldInfo.GetValue(object) will throw a NotSupportedException if:
"A field is marked literal, but the field does not have one of the
accepted literal types."
I have no idea what it means to
"mark a field as literal."
I want to understand this so that I may know how to guard against this exception.
A literal is a const field. Every const field has its value determined at compile time, by initialization from a literal. Look at this code
using System;
using System.Reflection;
public class Program
{
const int literal_int = 5;
readonly int literal_int_two = 5;
const string literal_string = "Fun";
const Random literal_random = null;
int non_literal;
public static void Main()
{
foreach (FieldInfo f in typeof(Program).GetFields(BindingFlags.Instance
| BindingFlags.NonPublic
| BindingFlags.Static
| BindingFlags.FlattenHierarchy))
{
Console.WriteLine("{0} is literal - {1}", f.Name, f.IsLiteral);
try
{
Console.WriteLine("GetValue = {0}", f.GetValue(null));
}
catch{}
}
}
}
Output:
literal_int is literal - True
GetValue = 5
literal_int_two is literal - False
literal_string is literal - True
GetValue = Fun
literal_random is literal - True
GetValue =
non_literal is literal - False
However,
but the field does not have one of the accepted literal types
is open to interpretation and I couldn't find an example for a literal that doesn't have 'one of the accepted literal types' (whatever that means).
By briefly looking at the source code, I couldn't find a relative piece of code to stand for this exception. You should be safe ignoring this clause.
Have a look at the FieldInfo.IsLiteral Property:
Gets a value indicating whether the value is written at compile time
and cannot be changed.
The IsLiteral property is set when the FieldAttributes.Literal
attribute is set. If this attribute is set, the field cannot be
changed and is constant.
The exception stated by
"A field is marked literal, but the field does not have one of the accepted literal types."
... have to be related to FieldInfo instances created by dynamic or custom code (rather than gathered through Reflection), where often certain validations are delayed or omitted.
A FieldInfo object contains meta-data that represents a field, but its class is inheritable and any derived implementation could potentially allow the bad type condition.
I'm trying to set up a class that has a dictionary with an int and my own object. On init I do not have anything to put in this dictionary.
class Menu
{
var emptyDic = Dictionary<String, String>()
var menuItem: Dictionary<Int,MenuItem>()
init()
{
//init object code
}
}
The emptyDic variable (which I got from StackOverflow) works fine, but I get an error consecutive declarations on a line must be separated by a ; if I mirror the same syntax for my menuItem dictionary. If I remove the () it complains that self.menuItem is not initialised.
I've not seen much written about dictionaries with other types other than strings. Is this a case for making it an optional or am I missing something more obvious?
Thanks
Andrew
You didn't copy the syntax. ':' and '=' are not equivalent. In this case, one specifies a type while the other specifies initialization.
Try:
var menuItem = Dictionary<Int,MenuItem>()
i am getting error "Object reference not set to an instance of an object." my is here,
public class UserProfession
{
public UserProfession()
{
}
public System.String[] Designation
{
get;
set;
}
}
then i am using it like,
UserProfession.Designation[0] =txt_Search.Text.ToString();
Error i mentioned you hopes for your suggestions .
-Thanks
When you make an assignment to an array property, like this:
UserProfession.Designation[0] =txt_Search.Text.ToString();
what you are actually doing is calling the get section for that property... not the set. This returns the object supported the property... the whole object, and not just the index. Index lookup does not happen until after the object is returned. Once you have that object, accessing an index works in the normal way.
You get this specific exception because you have the expression UserProfession.Designation that should return a reference to an array object, but because you never initialize the array there is nothing there when you then try to find reference the 0th element. At this point the framework discovers that the array (your "object reference") is "not set to an instance of an object"... which is just a fancy way of saying it's null.
In other words, you need to have an already existing array to hold the value you want to assign. That means doing something like this:
Designation = new String[10];
public String[] Designation
{
get;
set;
}
However, notice that we never used the set section? So you can simplify that further, like this:
Designation = new String[10];
public String[] Designation {get;private set;}
This will keep client code from completely swapping an entire array out from under your object, but otherwise will provide the full functionality of an array property. If you provide your own backing store for the array, you could even get rid of the setter entirely with no loss of functionality:
private string[] _designation = new string[10];
public string[] Designation {get {return _designation;} }
But let's add one more wrinkle: your desire to assign the to array before initializing it indicates to me that you likely don't really know how big it will be up front. If that's the case, you probably want a collection of some kind instead of an array. A generic List is a convenient and very compatible replacement for an array. That would look like this:
private List<string> _designation = new List<string>();
public List<string> Designation {get {return _designation;}}
You can still access items in that list by index, just like you would with an array. The only difference you need to worry about right now is how you add new items:
UserProfession.Designation.Add(txt_Search.Text);
Also notice that I removed the .ToString() call. Since your .Text property is almost certainly already a string, calling the .ToString() method is just silly.
You will have to initialize the object, before assigning the value. The initialization should be done just once. I have initialized the array size to ten. You can have your own values here. If you want to resize dynamically, you can use ArrayList
int length = 10;
UserProfession.Designation = new System.String[length];
UserProfession.Designation[0] =txt_Search.Text.ToString();
For more information: http://msdn.microsoft.com/en-us/library/aa287601(v=vs.71).aspx
it must initialize the value before we use because, currently, it is null.
you better add the initialization code in the constructor function.
Assumed I defined my dict as below.
Dictionary<list<int>, list<string>> d = new Dictionary<List<int>, list<string>>()
How can I retrieve the dict key and value rapidly.
[update]
I want to get the Key - List content.
I tried a simple way as below
List<int> KeysList= new List<int>(d.Keys);
But it doesn't work at the complex key on my case.
Can I only use the KeyValuePair as below?
foreach (KeyValuePair<List<int>, List<string>> pair in d)
{
KeysList= new List<int>(pair.Key);
}
You've got a potential problem there to start with: List<T> doesn't override Equals, so you'd have to use the exact same key reference to fetch the value for a key.
Having said that, if you have that reference, it's as simple as
List<string> value = d[key];
or
List<string> value;
if (d.TryGetValue(key, out value))
{
...
}
It's pretty unusual to have a List<T> as a key though - can you tell us more about what you're trying to do? There may be a better approach.