Dictionary<string, object> to object - c#

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.

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.

c# initialize expandoobject from list<T>

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 };
}

C# generic method returning different object instances [duplicate]

Are there any elegant quick way to map object to a dictionary and vice versa?
Example:
IDictionary<string,object> a = new Dictionary<string,object>();
a["Id"]=1;
a["Name"]="Ahmad";
// .....
becomes
SomeClass b = new SomeClass();
b.Id=1;
b.Name="Ahmad";
// ..........
Using some reflection and generics in two extension methods you can achieve that.
Right, others did mostly the same solution, but this uses less reflection which is more performance-wise and way more readable:
public static class ObjectExtensions
{
public static T ToObject<T>(this IDictionary<string, object> source)
where T : class, new()
{
var someObject = new T();
var someObjectType = someObject.GetType();
foreach (var item in source)
{
someObjectType
.GetProperty(item.Key)
.SetValue(someObject, item.Value, null);
}
return someObject;
}
public static IDictionary<string, object> AsDictionary(this object source, BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)
{
return source.GetType().GetProperties(bindingAttr).ToDictionary
(
propInfo => propInfo.Name,
propInfo => propInfo.GetValue(source, null)
);
}
}
class A
{
public string Prop1
{
get;
set;
}
public int Prop2
{
get;
set;
}
}
class Program
{
static void Main(string[] args)
{
Dictionary<string, object> dictionary = new Dictionary<string, object>();
dictionary.Add("Prop1", "hello world!");
dictionary.Add("Prop2", 3893);
A someObject = dictionary.ToObject<A>();
IDictionary<string, object> objectBackToDictionary = someObject.AsDictionary();
}
}
Convert the Dictionary to JSON string first with Newtonsoft.
var json = JsonConvert.SerializeObject(advancedSettingsDictionary, Newtonsoft.Json.Formatting.Indented);
Then deserialize the JSON string to your object
var myobject = JsonConvert.DeserializeObject<AOCAdvancedSettings>(json);
Seems reflection only help here.. I've done small example of converting object to dictionary and vise versa:
[TestMethod]
public void DictionaryTest()
{
var item = new SomeCLass { Id = "1", Name = "name1" };
IDictionary<string, object> dict = ObjectToDictionary<SomeCLass>(item);
var obj = ObjectFromDictionary<SomeCLass>(dict);
}
private T ObjectFromDictionary<T>(IDictionary<string, object> dict)
where T : class
{
Type type = typeof(T);
T result = (T)Activator.CreateInstance(type);
foreach (var item in dict)
{
type.GetProperty(item.Key).SetValue(result, item.Value, null);
}
return result;
}
private IDictionary<string, object> ObjectToDictionary<T>(T item)
where T: class
{
Type myObjectType = item.GetType();
IDictionary<string, object> dict = new Dictionary<string, object>();
var indexer = new object[0];
PropertyInfo[] properties = myObjectType.GetProperties();
foreach (var info in properties)
{
var value = info.GetValue(item, indexer);
dict.Add(info.Name, value);
}
return dict;
}
I'd highly recommend the Castle DictionaryAdapter, easily one of that project's best-kept secrets. You only need to define an interface with the properties you want, and in one line of code the adapter will generate an implementation, instantiate it, and synchronize its values with a dictionary you pass in. I use it to strongly-type my AppSettings in a web project:
var appSettings =
new DictionaryAdapterFactory().GetAdapter<IAppSettings>(ConfigurationManager.AppSettings);
Note that I did not need to create a class that implements IAppSettings - the adapter does that on the fly. Also, although in this case I'm only reading, in theory if I were setting property values on appSettings, the adapter would keep the underlying dictionary in sync with those changes.
I think you should use reflection. Something like this:
private T ConvertDictionaryTo<T>(IDictionary<string, object> dictionary) where T : new()
{
Type type = typeof (T);
T ret = new T();
foreach (var keyValue in dictionary)
{
type.GetProperty(keyValue.Key).SetValue(ret, keyValue.Value, null);
}
return ret;
}
It takes your dictionary and loops through it and sets the values. You should make it better but it's a start. You should call it like this:
SomeClass someClass = ConvertDictionaryTo<SomeClass>(a);
Reflection can take you from an object to a dictionary by iterating over the properties.
To go the other way, you'll have to use a dynamic ExpandoObject (which, in fact, already inherits from IDictionary, and so has done this for you) in C#, unless you can infer the type from the collection of entries in the dictionary somehow.
So, if you're in .NET 4.0 land, use an ExpandoObject, otherwise you've got a lot of work to do...
Building on Matías Fidemraizer's answer, here is a version that supports binding to object properties other than strings.
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace WebOpsApi.Shared.Helpers
{
public static class MappingExtension
{
public static T ToObject<T>(this IDictionary<string, object> source)
where T : class, new()
{
var someObject = new T();
var someObjectType = someObject.GetType();
foreach (var item in source)
{
var key = char.ToUpper(item.Key[0]) + item.Key.Substring(1);
var targetProperty = someObjectType.GetProperty(key);
//edited this line
if (targetProperty.PropertyType == item.Value.GetType())
{
targetProperty.SetValue(someObject, item.Value);
}
else
{
var parseMethod = targetProperty.PropertyType.GetMethod("TryParse",
BindingFlags.Public | BindingFlags.Static, null,
new[] {typeof (string), targetProperty.PropertyType.MakeByRefType()}, null);
if (parseMethod != null)
{
var parameters = new[] { item.Value, null };
var success = (bool)parseMethod.Invoke(null, parameters);
if (success)
{
targetProperty.SetValue(someObject, parameters[1]);
}
}
}
}
return someObject;
}
public static IDictionary<string, object> AsDictionary(this object source, BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)
{
return source.GetType().GetProperties(bindingAttr).ToDictionary
(
propInfo => propInfo.Name,
propInfo => propInfo.GetValue(source, null)
);
}
}
}
public class SimpleObjectDictionaryMapper<TObject>
{
public static TObject GetObject(IDictionary<string, object> d)
{
PropertyInfo[] props = typeof(TObject).GetProperties();
TObject res = Activator.CreateInstance<TObject>();
for (int i = 0; i < props.Length; i++)
{
if (props[i].CanWrite && d.ContainsKey(props[i].Name))
{
props[i].SetValue(res, d[props[i].Name], null);
}
}
return res;
}
public static IDictionary<string, object> GetDictionary(TObject o)
{
IDictionary<string, object> res = new Dictionary<string, object>();
PropertyInfo[] props = typeof(TObject).GetProperties();
for (int i = 0; i < props.Length; i++)
{
if (props[i].CanRead)
{
res.Add(props[i].Name, props[i].GetValue(o, null));
}
}
return res;
}
}
If you are using Asp.Net MVC, then take a look at:
public static RouteValueDictionary AnonymousObjectToHtmlAttributes(object htmlAttributes);
which is a static public method on the System.Web.Mvc.HtmlHelper class.
public Dictionary<string, object> ToDictionary<T>(string key, T value)
{
try
{
var payload = new Dictionary<string, object>
{
{ key, value }
};
} catch (Exception e)
{
return null;
}
}
public T FromDictionary<T>(Dictionary<string, object> payload, string key)
{
try
{
JObject jObject = (JObject) payload[key];
T t = jObject.ToObject<T>();
return (t);
}
catch(Exception e) {
return default(T);
}
}

Sorting a list of dictionaries based on a key

I have a list of dictionaries which contains student data
It is something like
List<Dictionary<string, object>> students = new List<Dictionary<string, object>>();
Dictionary<string, object> std1 = new Dictionary<string, object>();
std1["name"] = "sai";
std1["age"] = 22;
std1["gender"] = "male";
students.Add(std1);
Dictionary<string, object> std2 = new Dictionary<string, object>();
std2["name"] = "Julia";
std2["gender"] = "female";
students.Add(std2);
Dictionary<string, object> std3 = new Dictionary<string, object>();
std3 ["name"] = "sunny";
std3 ["age"] = 23;
students.Add(std3);
And I want to sort the list of students based on either name, age or gender, I am trying something like this:
var ordered = students.OrderBy(x => x["name"]);
If I try with either age or gender it is returning an error that key is not found, as std2 doesn't have age and std3 doesn't have gender.
I need all the records even it doesn't contain the value for sorted key, Any way to solve this problem, Thanks in advance.
It is better to create a class like this:
public class YourClass
{
public string Name { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
}
Then:
List<YourClass> students = new List<YourClass>();
YourClass std1 = new YourClass();
std1.Name = "sai";
std1.Age = 22;
std1.Gender = "male";
students.Add(std1);
yourClass std2 = new yourClass();
std2.Name = "Julia";
std2.Gender = "female";
students.Add(std2);
yourClass std3 = new yourClass();
std3.Name = "sunny";
std3.Age = 23;
students.Add(std3);
var ordered = students.OrderBy(x => x.Name);
This arrangement stores the same data you had in multiple dictionaries. However, it's far more clear and understandable.
If you want to sort by a key that is not present in all of the dictionaries, you'll need to return a default value instead, for example 0.
var ordered = students.OrderBy(dict =>
{
string name;
if (!dict.TryGetValue("name", out name))
return "";
return name;
});
Shorter version using the conditional ternary operator:
var ordered = students.OrderBy(dict =>
{
string name;
return dict.TryGetValue("name", out name) ? name : 0;
});
I use Dictionary.TryGetValue(...) which returns a bool depicting whether the key was found in the dictionary and its value returned.
You can solve this problem by supplying a GetOptional method that returns some default object in situations when the dictionary does not have a specific key:
V GetOptional<K,V>(IDictionary<K,V> d, K key, V absent) {
V res;
return d.TryGetValue(key, out res) ? res : absent;
}
Now you can sort like this:
var byName = students.OrderBy(x => GetOptional<string,object>(x, "name", "----"));
var byAge = students.OrderBy(x => GetOptional<string,object>(x, "age", "10000"));
Note: Using dictionaries like this gives you flexibility at the expense of clarity. It is usually better to define a special Student type, rather than using a universal collection of key-value pairs.

Newly created item field values

When creating a new item; is there any way to access all the field values that are set.
Since I'm using Entity.GetModifiedMembers() method to access the values of the fields that are changed when updating for logging purposes, the purpose is to have the equivalent result through an entity when creating, like a method Entity.GetSetMembers().
So in general, all I need is a key-value pair with "member name" and "value" items.
Example:
public class SomethingEntity
{
public int Id {get;set;}
public string Name {get;set;}
public DateTime Created {get;set;}
public DateTime Modified {get;set;}
}
public Dictionary<string, string> GetFieldsAndValuesOfCreatedItem(object entity)
{
//This is what I need, that can take all the objects from an entity and give
//the property-value pairs for the object instance
return RequieredMethod(entity);
}
public ExampleMethod()
{
var newObject = new SomethingEntity() { Name = "SomeName", Created = DateTime.Now };
Entity.insetOnSubmit(newObject);
Entity.SubmitChanges();
var resultList = GetFieldsAndValuesOfCreatedItem(newObject);
foreach (var propertyKeyValue in resultList)
{
var propertyString = "Property Name: " + propertyKeyValue.Key;
var valueString = "Value : " + propertyKeyValue.Value;
}
}
I've found out that, Reflection is the answer for that as far as I could find: so here is the method I've come up with:
public static Dictionary<string, string> GetFieldsAndValuesOfCreatedItem(object item)
{
var propertyInfoList = item.GetType().GetProperties(BindingFlags.DeclaredOnly |
BindingFlags.Public |
BindingFlags.Instance);
var list = new Dictionary<string, string>();
foreach (var propertyInfo in propertyInfoList)
{
var valueObject = propertyInfo.GetValue(item, null);
var value = valueObject != null ? valueObject.ToString() : string.Empty;
if (!string.IsNullOrEmpty(value))
{
list.Add(propertyInfo.Name, value);
}
}
return list;
}

Categories