I have a dictionary collection of more than 100 fields and values. Is there a way to populate a gigantic class with a 100 fields using this collection?
The key in this dictionary corresponds to the property name of my class and the value would be the Value of the Property for the class.
Dictionary<string, object> myDictionary = new Dictionary<string, object>();
myDictionary.Add("MyProperty1", "Hello World");
myDictionary.Add("MyProperty2", DateTime.Now);
myDictionary.Add("MyProperty3", true);
Populates the properties of the following class.
public class MyClass
{
public string MyProperty1 {get;set;}
public DateTime MyProperty2 {get;set;}
public bool MyProperty3 {get;set;}
}
You can use GetProperties to get a list of properties for a given type and use SetValue to set a specific value for a given property:
MyClass myObj = new MyClass();
...
foreach (var pi in typeof(MyClass).GetProperties())
{
object value;
if (myDictionary.TryGetValue(pi.Name, out value)
{
pi.SetValue(myObj, value);
}
}
Use
MyClass yourinstance...
foreach (var KVP in myDictionary)
{
yourinstance.GetType().GetProperty ( KVP.Key ).GetSetMethod().Invoke ( yourinstance, new object[] { KVP.Value } );
}
Related
I need to convert all my dictionary objects that coming from an api which are stored in results(model) to StudentList type.
I am doing it for one property as shown below:
StudentList<StudentData> testList = new StudentList<StudentData>();
foreach(KeyValuePair<string, IEnumerable<StudentData>> pair in result.StudentDataDetails)
{
foreach(var x in pair.Value)
testList.Add(x);
}
Like StudentData , there are other class objects like TeacherData, ParentData.. all these need to changed to StudentList<TeacherData>, StudentList<ParentData>.
I am trying to build a generic method for this..any help would be appreciated. I need to check if there is a dictionary property from results in the following way Dictionary<string, IEnumerable<T>> then change the dictionary as mentioned above. T is StudentData, TeacherData and so on. The generic method needs to return the StudentList<T>.
Thank you
You can write a generic method that takes in a dictionary of type <string, IEnumerable<T>> and returns a List<T> from all the values. This will work for any type T, whether it's a Student, Teacher, Parent, etc:
public static List<T> GetAllValues<T>(Dictionary<string, IEnumerable<T>> input)
{
return input?.SelectMany(kvp => kvp.Value).ToList();
}
Sample usage:
var studentDict = new Dictionary<string, IEnumerable<Student>>
{
{"1", new List<Student> {new Student {Name = "First"}}},
{"2", new List<Student> {new Student {Name = "Second"}}},
{
"3", new List<Student>
{
new Student {Name = "Third"},
new Student {Name = "Fourth"}
}
},
};
var studentList = GetAllValues(studentDict);
studentList.ForEach(s => Console.WriteLine(s.Name));
Output
I dont know how works your classe StudentList, but, i built a sample that could help you.
public class StudentReaderAPI
{
public StudentList<T> BuildList<T>(Dictionary<string, IEnumerable<T>> dataDetails) where T : AbstractDataDetails
{
if (dataDetails == null) return null;
return new StudentList<T>(dataDetails.Values.SelectMany(x => x));
}
}
public class StudentList<T> : List<T> where T : AbstractDataDetails
{
public StudentList(IEnumerable<T> enumerable) : base(enumerable)
{
}
//Your List logic here
}
public abstract class AbstractDataDetails
{
//Common properties of DataDetails
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class StudentData : AbstractDataDetails
{
//StudentData Properties here
}
public class ParentData : AbstractDataDetails
{
//ParentData Properties here
}
public class TeacherData : AbstractDataDetails
{
//TeacherData Properties here
}
You can create the generic method which take the dictionary as input
public StudentList<T> GenericMethod(Dictionary<string, T> dictionary)
{
StudentList<T> testList = new StudentList<T>();
foreach(KeyValuePair<string, IEnumerable<T>> pair in dictionary)
{
foreach(var x in pair.Value)
testList.Add(x);
}
return testList;
}
Then call this method and pass the dictionary
GenericMethod(result.StudentDataDetails);
GenericMethod(result.TeacherDataDetails);
I create a dictionary as you can see :
public Dictionary<string, string> TipList
{
get { return TipList; }
set { TipList = value; }
}
I fetch some data from a service and I want to put these data into my dictionary as you can see here :
Dictionary<string, string> dict = new Dictionary<string, string>();
try
{
using (var response = (HttpWebResponse)request.GetResponse())
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
var objText = reader.ReadToEnd();
var list = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(objText).ToDictionary(x => x.Keys, x => x.Values);
object o;
object o1;
foreach (var item in list)
{
o = item.Value.ElementAt(0);
o1 = item.Value.ElementAt(1);
dict.Add(o.ToString(), o1.ToString());
}
GlobalVariable.TipListCache.Add(NewCarReceiption.CSystem.Value, dict);
NewCarReceiption.TipList = dict.Where(i=>i.Key!=null & i.Value!=null).ToDictionary(x => x.Key, x => x.Value);
}
}
}
But after running my code when the above function is trying to put their data into my dictionary .my application returns this error :
Your setter is calling the TipList property's setter (itself) which is calling its setter and so on - resulting in the exception.
Initialize it like this:
private Dictionary<string, string> _tipList;
public Dictionary<string, string> TipList
{
get { return _tipList; }
set { _tipList = value; }
}
Or best, if you do not need any behavior other than the default, with the auto-implemented property:
public Dictionary<string, string> TipList { get; set; }
and since C# 6.0 you can also initialize it like this ( with Auto-property initializers):
public Dictionary<string, string> TipList { get; set; } = new Dictionary<string, string>();
You are setting the same property over and over again, going into an infinite loop.
If you don't need any additional logic in your getter and setter, you might just leave it auto-implemented:
public Dictionary<string, string> TipList
{
get;
set;
}
If you do need more logic in your getter and setter, you have to add a backing field yourself:
private Dictionary<string, string> tipList;
public Dictionary<string, string> TipList
{
get
{
DoSomethingBeforeGet();
return this.tipList;
}
set
{
DoSomethingBeforeSet();
this.tipList = value;
DoSomethingAfterSet();
}
}
Good day,
I need to make function that will iterate on Dictionary that stores variable name and variable`s new value. After that, I need to update class variable with that value.
void UpdateValues(Type type, Dictionary<string, string> values)
{
foreach (var value in values)
{
var fieldInfo = selected.GetComponent(type).GetType().GetField(value.Key);
if (fieldInfo == null) continue;
fieldInfo.SetValue(selected.GetComponent(type), value.Value);
}
}
It works but I want little improvement and I absolutely don't know if it is possible.
As you can see, that function can accept any class, not just one specific.
If I have class like this
class test
{
public string age;
}
And I would use function this way, it would work.
UpdateValues(typeof(test), new Dictionary<string, string>{{"age", "17"}});
Problem is if I have class like this and I would like to update "subfield" (field in field)
class test
{
public string age;
}
class test2
{
public test data;
}
I was thinking that syntax could be something like this, but I have no idea how could I do it.
UpdateValues(typeof(test2), new Dictionary<string, string>{{"data.age", "17"}});
To sum it up, I need to make function that will take class that is stored in another class. Function will iterate trough the dictionary and update fields of class and even her subfields.
I would propose to add a recursive call to your method, to set the properties. I have changed your method a little bit, because i don't have selected object, it takes an object as a parameter
void UpdateValues<T>(T obj, Dictionary<string, string> values)
{
foreach (var value in values)
{
SetProperty(obj, value.Key, value.Value);
}
}
public void SetProperty<T>( T obj, string valueKey, string value, Type type= null)
{
var typeToUse = type ?? typeof(T);
var pointIndex = valueKey.IndexOf(".");
if (pointIndex!=-1)
{
var subKey = valueKey.Substring(0, pointIndex);
var fieldInfo = typeToUse.GetField(subKey);
var propObj = fieldInfo.GetValue(obj)
?? Activator.CreateInstance(fieldInfo.FieldType);
SetProperty(propObj, valueKey.Substring(pointIndex+1), value, fieldInfo.FieldType);
fieldInfo.SetValue(obj, propObj);
}
else
{
var fieldInfo = typeToUse.GetField(valueKey);
if (fieldInfo != null)
fieldInfo.SetValue(obj, value);
}
}
It works even if you define
class test3
{
public test2 data;
}
and call
UpdateValues(t, new Dictionary<string, string>{{"age", "17"}});
UpdateValues(t2, new Dictionary<string, string> { { "data.age", "17" } });
UpdateValues(t3, new Dictionary<string, string> { { "data.data.age", "17" } });
The third parameter of SetProperty method is not really nice, i would avoid it, but i don't know how to solve it with generics, after creating with Activator you get object as a Type, and object doesn't have field age
You are using Dictionary<string, string> as a parameter that allows you to set only string fields, so you must assume that you don't have any other. Actually this will work even if you will use Dictionary<string, object>, that i would suggest to do.
First of all you will need to change your Dictionary variable to use
Dictionary<string, object> if you want to pass a class as a parameter in here.
Secondly Here is an example of how to make it work.
class test
{
public string age;
}
class test2
{
public test data;
}
Lets suppose i have created an instance of test class and added it in a dictionary, to get the fields with reflection and then update the instance of test2 accordingly.
public void UpdateValues(object test2, Dictionary<string, object> dict)
{
var fieldValues = test2.GetType()
.GetFields()
.ToList();
foreach (var value in dict)
{
foreach (var field in fieldValues)
{
if (value.Key == field.Name)
{
bool obj = field.FieldType == typeof(test);
if (obj)
{
if (dict.ContainsKey("data"))
{
var prop = test2.GetType().GetField("data", System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.Instance);
prop.SetValue(test2, dict["data"]);
break;
}
}
else
{
var prop = test2.GetType().GetField(value.Key, System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.Instance);
prop.SetValue(test2, value.Value);
break;
}
}
}
}
}
In the end call you function i have created a Dictionary<string,object> instance to send it as a parameter to the function
object test2 = new test2();
test t = new test();
t.age = "10";
Dictionary<string, object> dict = new Dictionary<string, object>();
dict.Add("data", t);
UpdateValues(test2, dict);
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;
}
Is this possible to do in C#?
I have POCO object here is definition:
public class Human
{
public string Name{get;set;}
public int Age{get;set;}
public int Weight{get;set;}
}
I would like to map properties of object Human to string array.
Something like this:
Human hObj = new Human{Name="Xi",Age=16,Weight=50};
Or I can have List<Human>:
string [] props = new string [COUNT OF hObj PROPERTIES];
foreach(var prop in hObj PROPERTIES)
{
props["NAME OF PROPERTIES"] = hObj PROPERTIES VALUE
}
It should be something like this:
var props = new Dictionary<string, object>();
foreach(var prop in hObj.GetType().GetProperties(BindingFlags.Public|BindingFlags.Instance);)
{
props.Add(prop.Name, prop.GetValue(hObj, null));
}
see here for info on GetProperties and here for PropertyInfo
You can use reflection to get an object's properties and values:
var properties = typeof(Human).GetProperties();
IList<KeyValuePair<string, object>> propertyValues = new List<KeyValuePair<string, object>>();
foreach (var propertyInfo in properties)
{
propertyValues.Add(propertyInfo.Name, propertyInfo.GetValue(oneHuman));
}