c# initialize expandoobject from list<T> - c#

I want to initialize an expandoObject from List.
internal class CarKeyValue {
public CarKey CarKey { get; set; }
public string Value1 { get; set; }
public string Value2 { get; set; }
}
public enum CarKey {
Brand = 1,
Model = 2,
Year = 3,
FactoryLocation = 4,
//more than 400 key here...
}
var car = new List<CarKeyValue>{
new CarKeyValue {CarKey = CarKey.Brand, Value1 = "Ford"},
new CarKeyValue {CarKey = CarKey.Model, Value1 = "Focus",Value2 = "Titanium"},
new CarKeyValue {CarKey = CarKey.Year, Value1 = "1995"},
new CarKeyValue {CarKey = CarKey.FactoryLocation, Value1 = "Turkey",Value2="Bursa"},
};
dynamic expando = new ExpandoObject();
foreach(var item in car){
expando.[item.CarKey].Value1 = item.Value1;
//Incorrect primary expression.
expando.[item.CarKey].Value2 = item.Value2;
}
How I do that? I need to use Expando Object. I try to use IDictionary<string,dynamic> but that thrown another exception.
Is there any possible way?

Yes, you can, but it makes no sense. You have to cast your expando object to IDictionary<string, object> or IDictionary<string, dynamic>.
IDictionary<string, object> expando = new ExpandoObject();
foreach (var item in car)
{
expando[item.CarKey.ToString()].Value1 = item.Value1;
}
The above code fails because you never assign a value to expando[item.CarKey.ToString()]. Instead you want to set a property from a non-existing object. Regular code would have thrown a NullReferenceException here. (You can read the above code as expando.SomeProperty.Value1, where SomeProperty is null.)
So once you have set the object to an instance of something, you can use it, but then there is not much use in using the ExpandoObject any more:
Foo foo = new Foo();
expando[item.CarKey.ToString()] = foo;
foo.Value1 = item.Value1;

My solution is here. I use IDictionary. Not neccessary using Foo() or something else. This code block working well.
IDictionary<string,dynamic> expando = new ExpandoObject();
foreach(var item in car) {
expando.Add(item.CarKey.ToString(),null);
expando[item.CarKey.ToString()] = new { Value1 = item.Value1,Value2 = item.Value2 };
}

Related

Iterate through a dictionary and use value to iterate through class C#

In my c# code, I have an iteration over a Dictionary and want to achieve something like so using Classes
MyModel othermodel = new MyModel();
Dictionary<string, string> mydictionary = new Dictionary<string, string>()
{
{"n1", "Item"},
{"n2", "Second"},
{"n3", "Third"},
{"n4", "Fourth"},
{"n5", "Fith"},
{"n6", "Sixth"},
{"n7", "Seventh"},
{"n8", "Eighth"},
{"n9", "Ninth"},
{"n0", "Tenth"},
{"n11", "Eleventh"}
};
foreach (var dicitem in mydictionary.ToArray())
{
foreach (MyModel.NewItem.(mydictionary[dicitem].Value) item in othermodel.(mydictionary[dicitem].Key))
{
...
}
}
So my result would be:
first iteration:
foreach (MyModel.NewItem.Item item in othermodel.n1)
{
...
}
second iteration:
foreach (MyModel.NewItem.Second item in othermodel.n2)
{
...
}
...
If there is a way to do this, any help would be appreciated.
Accessing object properties via its names can be done using Reflection, doesn't matter where these names come from (dictionary, array, ...)
Little example here:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
then to access the Name property you do:
var me = new Person {Name = "John", Age = 33};
var propertyName = "Name";
var propertyInfo = typeof(Person).GetProperty(propertyName);
var propertyValue = propertyInfo?.GetValue(me) as string;
Using the upper code, you create one Propertynfo.
If you want to read more properties of the same object, it is better to read all PropertyInfo objects at once:
var me = new Person {Name = "John", Age = 33};
var propertiesInfo = typeof(Person).GetProperties();
var propertyName = "Name";
var nameProperty = propertiesInfo
.Single(p => p.Name == propertyName);
var name = nameProperty.GetValue(me) as string;
//faster approach
var age = (int)propertiesInfo
.Single(p => p.Name == "Age")
.GetValue(me);
Be be aware that in this example, I suppose that the property with specific name exists, so I simply called Single. In different situation however, it may require you to check the existence of property before accessing it.

Dot Notation Alternatives

I am wondering if there is an alternative to dot notation in C#. For instance, in Javascript, I can have an object like this:
const myObj = { foo: "bar" }
And then I can reference it like this:
let x = "foo";
let y = myObj[x]; //sets y = "bar"
Is this possible in C#? I have not found anything of the sort, but am wondering if there are alternatives that would function similarly.
You can implement an indexer in your class:
public class A
{
public int X { get; set; }
public string Y { get; set; }
public object this[string name]
{
get => GetType().GetProperty(name).GetValue(this, null);
set => GetType().GetProperty(name).SetValue(this, value);
}
}
Then use it:
var a = new A();
a["X"] = 10;
a["Y"] = "abc";
Console.WriteLine(a.X);
Console.WriteLine(a.Y);
You can have something similar using dynamic but you have to explicitly get the dictionary interface to use the array syntax.
dynamic myObject = new ExpandoObject();
myObject.greeting = "hello";
IDictionary<string, object> myDict = myObject;
Console.WriteLine(myDict["greeting"]);
Note that it works in both directions. You can add that after the previous code:
myDict["name"] = "Joe";
Console.WriteLine(myObject.name);
You can have both syntax if you don't mind having an intermediate object like myObject.something.name.
The code would look like:
void Main()
{
BothSyntax test= new BothSyntax();
test.dyn.greeting = "Hi";
Console.WriteLine(test["greeting"]);
test["name"] = "Joe";
Console.WriteLine(test.dyn.name);
}
class BothSyntax
{
public dynamic dyn => eo;
private ExpandoObject eo = new ExpandoObject();
public object this[string key]
{
get
{
return ((IDictionary<string, object>)eo)[key];
}
set
{
((IDictionary<string, object>)eo)[key] = value;
}
}
}

How to Convert a String returned from JSON to Object Dot Notation In C# & JSON.Net

I'm using C# and JSON.Net to read this JSON document:
{
"myValue": "foo.bar.baz"
}
My goal is to use the string value "foo.bar.baz" as object dot notation to access the value of foo.bar.baz in the foo object:
public Foo foo = new Foo();
var client = new WebClient();
client.Headers.Add("User-Agent", "Nobody");
var json = client.DownloadString(new Uri("http://www.example.com/myjson.json"));
JObject o = JObject.Parse(json);
foreach (JProperty prop in o.Children<JProperty>()){
Response.Write(????); // should write "Hello World!"
}
Just for reference, here is the Foo class:
public class Foo {
public Foo() {
this.bar = new Foo();
this.bar.baz = "Hello World";
}
}
Assuming you have an object with a property named foo, you could use reflection to find the value you are looking for. This would work for fields, but don't do that, use public properties instead.
public class SomeContainer
{
public Foo foo { get; set; }
}
var container = new SomeContainer();
var myValuePath = "foo.bar.baz"; // Get this from the json
string[] propertyNames = myValuePath.Split('.');
object instance = container;
foreach (string propertyName in propertyNames)
{
var instanceType = instance.GetType();
// Get the property info
var property = instanceType.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
// Get the value using the property info. 'null' is passed instead of an indexer
instance = property.GetValue(instance, null);
}
// instance will be baz after this loop
There are all sorts of potential NullReferenceException so you'll have to code this more defensively. However, this should be a good start for you.

Dictionary<string, object> to object

What the best way convert this dictionary:
Dictionary<string, object> person = new Dictionary<string, object>();
person.Add("ID", 1);
person.Add("Name", "Alex");
to object:
public class Person
{
public int ID{get;set;}
public string Name{get;set;}
}
?
Here is my suggestion:
var newPerson = new Person
{
ID = (int)person["ID"],
Name = person["Name"].ToString()
};
This has no error handling and is assuming that the fields exists in the dictionary and are filled with valid values!
If you want to be able to do this for any object in general, you could use reflection. Assuming the values in the dictionary are the appropriate type and requires no conversion:
static T GetObject<T>(Dictionary<string, object> dict)
where T : new()
{
var obj = new T();
foreach (var property in typeof(T).GetProperties())
{
var args = new object[1];
var setter = property.GetSetMethod(); // property has a public setter
if (setter != null && dict.TryGetValue(property.Name, out args[0]))
setter.Invoke(obj, args);
}
return obj;
}
Then to use it:
var alexDict = new Dictionary<string, object>
{
{ "ID", 1 },
{ "Name", "Alex" },
};
var alexPerson = GetObject<Person>(alexDict);
Person myPerson = new Person();
myPerson.ID = (int)person["ID"];
myPerson.Name = (string)person["Name"];
Provides no error checking with the int cast.
The easy way:
var person = new Person
{
Id = (int)dict["ID"],
Name = (string)dict["Name"]
}
The generic way: use reflection.

How to extend an object of the anonymous class

I have class method:
public object MyMethod(object obj)
{
// I want to add some new properties example "AddedProperty = true"
// What must be here?
// ...
return extendedObject;
}
And:
var extendedObject = this.MyMethod( new {
FirstProperty = "abcd",
SecondProperty = 100
});
Now the extendedObject has new properties. Help please.
You can't do that.
If you want a dynamic type that you can add members to at runtime then you could use an ExpandoObject.
Represents an object whose members can be dynamically added and removed at run time.
This requires .NET 4.0 or newer.
You can use a Dictionary (property, value) or if you are using c# 4.0 you can use the new dynamic object (ExpandoObject).
http://msdn.microsoft.com/en-us/library/dd264736.aspx
Do you know at compile-time the names of the properties? Because you can do this:
public static T CastByExample<T>(object o, T example) {
return (T)o;
}
public static object MyMethod(object obj) {
var example = new { FirstProperty = "abcd", SecondProperty = 100 };
var casted = CastByExample(obj, example);
return new {
FirstProperty = casted.FirstProperty,
SecondProperty = casted.SecondProperty,
AddedProperty = true
};
}
Then:
var extendedObject = MyMethod(
new {
FirstProperty = "abcd",
SecondProperty = 100
}
);
var casted = CastByExample(
extendedObject,
new {
FirstProperty = "abcd",
SecondProperty = 100,
AddedProperty = true
}
);
Console.WriteLine(xyz.AddedProperty);
Note that this relies very heavily on the fact that two anonymous types in the same assembly with properties having the same name of the same type in the same order are of the same type.
But, if you're going to do this, why not just make concrete types?
Output:
True

Categories