I have a dynamic object whose property begins with number. How to access this property?
For inst:
myResult.123; // this is unvalid
Any helps would be very appreciated.
If you are using ExpandoObject for your dynamic object, you can cast to IDictionary<string, object> and use an indexer;
dynamic expando = new ExpandoObject();
var dict = (IDictonary<string, object>)expando;
dict["123"] = 2;
Many other dynamic object implementations (e. g. JObject in Json.NET) provide similar functionality.
Here's an example with JObject:
var json = JsonConvert.SerializeObject(new Dictionary<string, object> { { "123", 10 } });
var deserialized = JsonConvert.DeserializeObject<object>(json);
// using the IDictionary interface
var ten = ((IDictionary<string, JToken>)deserialized)["123"].Value<JValue>().Value;
Console.WriteLine(ten.GetType() + " " + ten); // System.Int64 10
// using dynamic
dynamic d = deserialized;
Console.WriteLine(d["123"].Value.GetType() + " " + d["123"].Value); // System.Int64 10
Modified
Type t = myResult.GetType();
PropertyInfo[] props = t.GetProperties();
Dictionary<string, object> dict = new Dictionary<string, object>();
foreach (PropertyInfo prp in props)
{
object value = GetPropValue(myResult, prp.Name);
dict.Add(prp.Name, value);
}
public static object GetPropValue(object src, string propName)
{
return src.GetType().GetProperty(propName).GetValue(src, null);
}
Related
I want to create a single object (possibly Dictionary) with string keys that will have different variable types as the value (string, int, bool, Dictionary<string,string> etc). Is this possible?
*I understand this might just be a fundamental difference of two languages AKA square peg round hole
You can use dynamic as values type, that match better than object to the question and you need no future castings:
var dictionary = new Dictionary<string, dynamic>();
dictionary.Add("1", 10);
dictionary.Add("2", "test");
dictionary.Add("3", true);
foreach ( var item in dictionary )
Console.WriteLine($"{item.Key} is type: {item.Value.GetType().Name} = {item.Value}");
Console.WriteLine();
int v = dictionary["1"] + 10;
Console.WriteLine(v);
string s = dictionary["2"] + " one";
Console.WriteLine(s);
bool b = !dictionary["3"];
Console.WriteLine(b);
Output
1 is type: Int32 = 10
2 is type: String = test
3 is type: Boolean = True
20
test one
False
https://learn.microsoft.com/dotnet/csharp/programming-guide/types/using-type-dynamic
A Dictionary<string, object> is roughly equivalent to an object in JavaScript.
Example:
var dictionary = new Dictionary<string, object>
{
"myString" = "helloWorld",
"myChild" = new Dictionary<string, object>
{
"myName" = "bobby tables"
}
};
var myString = (string)dictionary["myString"];
var myName = (string)((Dictionary<string, object>)dictionary["myChild"])["myName"];
You can also use the dynamic keyword and ExpandoObject.
dynamic obj = new ExpandoObject();
obj.MyString = "helloWorld";
obj.MyChild = new ExpandoObject();
obj.MyChild.MyName = "bobby tables";
string myString = obj.MyString;
string myName = obj.MyChild.MyName;
how to convert :
A List :
var list = new List<string>(){"str1","str2"}
to a anonymous object :
var anonymousObject = new {str1 = "str1",str2 = "str2"}
during runtime
You can use the ExpandoObject which will give you the feature of dynamic type.
var list = new List<string>() { "str1", "str2" };
ExpandoObject obj = new ExpandoObject();
var store = (IDictionary<string, object>)obj;
list.ForEach(x => store.Add(x, x));
dynamic lst = obj;
var val = lst.str1; // Test
You can also use extension method represented below (from here).
Because converting list to dynamic object by iterating on items manually can be painful when there is many situations like this in your application.
You can use this extension method like this:
dynamic list = new List<string>() { "str1", "str2" }
.ToDictionary(dd => dd, dd => (object)dd)
.ToExpando();
The extension method:
public static ExpandoObject ToExpando(this IDictionary<string, object> dictionary)
{
var expando = new ExpandoObject();
var expandoDic = (IDictionary<string, object>)expando;
// go through the items in the dictionary and copy over the key value pairs)
foreach (var kvp in dictionary)
{
// if the value can also be turned into an ExpandoObject, then do it!
if (kvp.Value is IDictionary<string, object>)
{
var expandoValue = ((IDictionary<string, object>)kvp.Value).ToExpando();
expandoDic.Add(kvp.Key, expandoValue);
}
else if (kvp.Value is ICollection)
{
// iterate through the collection and convert any strin-object dictionaries
// along the way into expando objects
var itemList = new List<object>();
foreach (var item in (ICollection)kvp.Value)
{
if (item is IDictionary<string, object>)
{
var expandoItem = ((IDictionary<string, object>)item).ToExpando();
itemList.Add(expandoItem);
}
else
{
itemList.Add(item);
}
}
expandoDic.Add(kvp.Key, itemList);
}
else
{
expandoDic.Add(kvp);
}
}
return expando;
}
I have JSON string, something like:
{"1":{"1":"driver","2":"New York, NY"},"2":{"3":"male","2":"Alabama"}}
I have two enums:
public enum StoragePrimaryKeys
{
Login = 1,
Account = 2
};
public enum StorageSecondaryKeys
{
JobTitle = 1,
JobId = 2,
JobLocation = 3,
RenewDate = 4,
ExpirationDate = 5
};
How can I deserialize this JSON to an object?
I thought to do the next thing:
var jss = new JavaScriptSerializer();
Dictionary<string, string> sData = jss.Deserialize<Dictionary<string, string>>(value);
string output = string.empty;
foreach (KeyValuePair<string, string> entry in sData)
{
if (Convert.ToInt32(entry.Key) == StorageSecondaryKeys.JobTitle) {
}
output += "\n key:" + entry.Key + ", value:" + entry.Value;
}
But maybe there is more efficient way?
I think It's a new question cause I have numbers in the keys that should be translated to the strings of the enums
Thanks.
It appears your data model should be as follows:
Dictionary<StoragePrimaryKeys, Dictionary<StorageSecondaryKeys, string>>
However, from experimentation, I found that JavaScriptSerializer does not support enums as dictionary keys, so you cannot deserialize to such an object directly. Thus you could deserialize to string-keyed dictionaries and convert using Linq:
var dict = new JavaScriptSerializer().Deserialize<Dictionary<string, Dictionary<string, string>>>(value)
.ToDictionary(
p => (StoragePrimaryKeys)Enum.Parse(typeof(StoragePrimaryKeys), p.Key),
p => p.Value.ToDictionary(p2 => (StorageSecondaryKeys)Enum.Parse(typeof(StorageSecondaryKeys), p2.Key), p2 => p2.Value));
This will produce the dictionary you want.
Alternatively, you could install json.net and deserialize directly to the desired dictionary, since Json.NET does support enum-keyed dictionaries:
var dict = JsonConvert.DeserializeObject<Dictionary<StoragePrimaryKeys, Dictionary<StorageSecondaryKeys, string>>>(value);
I have an object:
MyObject obj = new MyObject();
obj.X = "Hello";
obj.Y = "World";
Someone passes me a string:
string myString = "obj.X";
I want to get the value referenced to myString, like this:
var result = <Some Magic Expression>(myString); // "Hello"
Is it possible through reflection?
You can't exactly replicate this behaviour, because names of local variables aren't saved in the method's metadata. However, if you keep a dictionary of objects, you can address the object by its key:
public static object GetProperty(IDictionary<string, object> dict, string path)
{
string[] split = path.Split('.');
object obj = dict[split[0]];
var type = obj.GetType();
return type.InvokeMember(split[1], BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetField | BindingFlags.GetProperty, null, obj, null);
}
var dict = new Dictionary<string, object>();
var cl = new MyClass();
dict["obj"] = cl;
cl.X = "1";
cl.Y = "2";
Console.WriteLine(GetProperty(dict, "obj.X"));
Console.WriteLine(GetProperty(dict, "obj.Y"));
This can handle accessing fields and properties in the format "name.property". Doesn't work for dynamic objects.
i have this
dynamic d = new ExpandoObject();
d.Name = attribute.QualifiedName.Name;
so , i know that d will have a property Name. Now if i don't know the name of the property at compile time , how do i add that property to the dynamic.
i found this SO Question
so, there is this complicated concept of call binders etc..which is tough to get in the first place.any simpler way of doing this ?
dynamic d = new ExpandoObject();
((IDictionary<string,object>)d)["test"] = 1;
//now you have d.test = 1
Here is a cleaner way
var myObject = new ExpandoObject() as IDictionary<string, Object>;
myObject.Add("Country", "Ireland");
You can also do like this:-
Dictionary<string,object> coll = new Dictionary<string,object>();
coll.Add("Prop1","hello");
coll.Add("Prop2",1);
System.Dynamic.ExpandoObject obj = dic.Expando();
//You can have this ext method to better help
public static ExpandoObject Expando(this IEnumerable<KeyValuePair<string, object>>
dictionary)
{
var expando = new ExpandoObject();
var expandoDic = (IDictionary<string, object>)expando;
foreach (var item in dictionary)
{
expandoDic.Add(item);
}
return expando;
}