Get properties of a Dynamic Type - c#

I would like to know how to get the properties of my dynamic type.
This is the function to get the List,
var result = _files.GetFileContent(reportId).Result;
As example I get an object returned like this :
When I open it, you can see the properties I have :
The Idea is that I never know the properties. They can change over time. So I want a list which is filled with all the properties. So I can dynamically use them.
How Can I get the properties from the first item (ChargesDelta_DIFF_5, ChargesEfile_RIGHT,ChargesGecep_LEFT, etc)?

You can use reflection to get the properties out and convert it to a dictionary:
dynamic v = new { A = "a" };
Dictionary<string, object> values = ((object)v)
.GetType()
.GetProperties()
.ToDictionary(p => p.Name, p => p.GetValue(v));

If someone is still struggling with this (as I did), this might be useful.
Let's say data is the dynamic you want to list all properties from:
This worked for me
using System.ComponentModel;
...
dynamic data = new {
value1 = 12,
value2 = "asdasd",
value3 = 98,
value4 = "pgiwfj",
};
foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(data))
{
Console.WriteLine("PROP: " + prop.Name);
}
...
Then it would output:
PROP: value1
PROP: value2
PROP: value3
PROP: value4
Source: https://social.msdn.microsoft.com/Forums/vstudio/en-US/251e4f3d-ce90-444a-af20-36bc11864eca/how-to-get-list-of-properties-of-dynamic-object-?forum=csharpgeneral

Related

List of objects, add properties together based of another property

I have a List that contains 2 properties per object. The properties are as follows:
string Project;
double Value;
So in any given case we might have a List of 5 objects, where 3 of them have a Project property called "Test" and the other 2 objects have a Project Property called "Others", but none of the 5 objects have the same "Value".
{
Project = "Test" Value = 1,
Project = "Test" Value = 5,
Project = "Test" Value = 25,
Project = "Others" Value = 89,
Project = "Others" Value = 151
}
Okay, I get a lot of data from a Database (I "Query" it out into a List of objects), then I take the specific properties I need from that List and add to my own List as follows.
public class Data
{
public string Project {get; set;}
public double Value {get; set;}
}
public List<Data> dataList = new List<Data>();
foreach(var item in DatabaseList)
{
Data newData = new Data(
data.Project = item.Project;
data.Value = item.Project;
dataList.Add(newData);
}
This gives me my list of data that I somehow need to combine based on the property in "Project"
But I have a hard time figuring out how to seperate them from one another, my first thought was to find "Unique" "Projects" and adding that to a new List called "counter", to then loop through that list based of the "Project" property, so something like this:
List<Data> counter = dataList.GroupBy(x => x.Project).Select(First()).ToList();
foreach(var item in counter)
{
Data finalItem = new Data();
foreach (var item2 in dataList)
{
if(item.Project == item2.Project)
{
finalItem.Project = item2.Project;
finalItem.Value += item2.Value;
finalList.Add(finalItem);
}
}
}
So I already know that the above is so messy its crazy, and its also not going to work, but this was the angle I was trying to take, I was also thinking whether I could maybe make use of Dictionary, but I feel like there is probably a super simple solution to something like this.
I think your initial thoughts regarding making use of a dictionary are good. Your use of .GroupBy() is a first step to create that dictionary, where the project name is the dictionary Key and the sum of values for that project is the dictionary Value.
You already seem to be familiar with the System.Linq namespace. The extension method .ToDictionary() exists in the same namespace, and can be used to define the Key and Value selector for each KeyValuePair (KVP) in the dictionary as follows:
.ToDictionary(
<selector for Key>,
<selector for Value>
);
The dictionary may be created by utilizing .ToDictionary() directly after .GroupBy(), as follows:
Dictionary<string, double> dataDictionary = dataList
.GroupBy(item => item.Project)
.ToDictionary(
itemsByProject => itemsByProject.Key,
itemsByProject => itemsByProject.Sum(item => item.Value));
Example fiddle here.
You can use the following code to compute the total Value for objects with Project="Test" :
double TestsValue = my_list.Where(o=>o.Project=="Test").Sum(t=>t.Value);
and do the same for "Others".
Assuming you're happy to return an IEnumerable of Data, you can do this:
var projects = dataList.GroupBy(p => p.Project)
.Select(grp =>
new Data
{
Project = grp.First().Project,
Value = grp.Sum(pr => pr.Value)
});

Get List of Fields - dynamic JSON

I have a very simple use case, I Decode a json response received from an API as following
dynamic data = Json.Decode(APIContents);
This decodes the JSON for me and put it in data object. The only thing I know about this JSON is that this is an array of objects and array is called result. So if I want to get the first item I can simply do the following to get the first item
data.result[0]
Similarly if I want the ID of first item, I know there is a field in json called id so I can get the ID as following
data.result[0].id
OR
data.result[0].["id"]
The problem is, I don't know all the field names, the only field I know is the ID but there are bunch of other fields and I want to read all of them.
How do get the list of all the fields from data.result object if I don't even know each field by name?
What I have tried
1- Loop through an object's properties and get the values for those of type DateTime
My code:
foreach (PropertyInfo prop in data.result[0].GetType().GetProperties())
{
// I dont get anything
}
2- Get properties of a Dynamic Type
My code:
Dictionary<string, object> values = ((object)data.result[0])
.GetType()
.GetProperties()
.ToDictionary(p => p.Name, p => p.GetValue(data.result[0]));
3- Using PropertyDescriptor
foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(data.result[0]))
{
// I get nothing
}
None of it is working, what am I doing wrong?
As you are operating with Json, would not you consider using something like JObject instead?
JObject o = new JObject
{
{ "name1", "value1" },
{ "name2", "value2" }
};
foreach (JProperty property in o.Properties())
{
Console.WriteLine(property.Name + " - " + property.Value);
}
// name1 - value1
// name2 - value2
foreach (KeyValuePair<string, JToken> property in o)
{
Console.WriteLine(property.Key + " - " + property.Value);
}
// name1 - value1
// name2 - value2

select column from list

I have a List<string> where are stored database table column name.
I need to select only this column (where name is stored into list) from a c# linq query.
Is possible?
I Try this code but I don't know how I can place in select:
I try this code
items = items.ToList();
_items.Add(new FieldItem() { FieldName = "field1" });
_items.Add(new FieldItem() { FieldName = "field2" });
_items.Add(new FieldItem() { FieldName = "field3" });
_items.Add(new FieldItem() { FieldName = "field4" });
_db.Table.Where(a => a.TimeStamp > DateTime.Now.AddHours(-1)).Select(....);
Thanks
Get Dapper via NuGet.
After that put in using in your code:
using Dapper;
And you're good to go. All you would need to do now is(using the example you have posted):
using (YourDbContext _db = new YourDbContext())
{
return _db.Database.Connection.Query($"SELECT {string.Join(",", _items.Select(if => if.FieldName))} FROM Table WHERE TimeStamp > #TimeStamp;", new { TimeStamp = DateTime.Now.AddDays(-1) });
}
This methods would return IEnumerable which would have all of your fields. The results can be casted into IDictionary where the key is your column name and the value is the actual value.
So for instance, if we were to get the first row in the results with First(), we could access the field values like this:
var value = ((IDictionary<string, object>)result.First())["column_name"];
Finally, I use reflection.
In string list are stored property name.
Get a property by name, and get it's value.
In this way get all PropertyInfo for a class:
PropertyInfo[] propertyInfos;
propertyInfos = typeof(MyClass).GetProperties(BindingFlags.Public |
BindingFlags.Static);
When property name match, update property value with:
property.SetValue(child, parentProperty.GetValue(parent));
Isn't an optimized solution, but works.

Printing list of enums in a particular namespace C#

Is there a way to print all the enums in C# class library or namespace? I want the name to be printed with its values.
For example if I have the namespace as below:
namespace MyCompany.SystemLib
{
public enum ItemStatus
{
None = 0,
Active = 1,
Inactive = 2
}
public enum MyEnum
{
EnumVal1 = 1,
EnumVal2 = 2,
EnumVal3 = 3,
}
}
I would like to print them delimited as below (to a textfile) Bullet given for clarity here not needed in output.
ItemStatus,None=0,Active=1,Inactive=1
MyEnum,EnumVal1=1,EnumVal2=2,EnumVal3
I don't know where to start. Any help is appreciated.
Reflection to the rescue!
List<string> allEnums = new List<string>();
var allTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(assembly => assembly.GetTypes());
foreach (Type type in allTypes)
{
if (type.Namespace == "MyCompany.SystemLib" && type.IsEnum)
{
string enumLine = type.Name + ",";
foreach (var enumValue in Enum.GetValues(type))
{
enumLine += enumValue + "=" + ((int)enumValue).ToString() + ",";
}
allEnums.Add(enumLine);
}
}
The first line goes over all assemblies currently loaded in memory (because a namespace can be scattered over many DLLs and EXEs) and filters out those in the right namespace, and that are enums. This can be streamlined into a LINQ query if you'd like.
The inner loop goes over the values of the enum, and uses GetName to match the string to the value.
Try using the Enum.GetNames() method.
It can be done using LINQ and Reflection ofcourse.
var asm = Assembly.LoadFrom("path of the assembly");
var enums = asm.GetTypes().Where(x => x.IsEnum).ToList();
var result = enums
.Select(
x =>
string.Format("{0},{1}", x.Name,
string.Join(",",Enum.GetNames(x)
.Select(e => string.Format("{0}={1}", e, (int)Enum.Parse(x, e))))));
File.WriteAllLines("path", result);

Incorrectly making new collection from existing collections

I am still a beginner with C# so I am sure I am missing some fundamental concept here but I am struggling with this.
I am trying to make a new collection from two existing collections.
The first is a Dictionary<string, someModel[]>
The second is a Dictionary<string, string>
I am trying to find matches between the two dicts keys and if they match make a new myOtherModelwith the values from the two dicts, but if they don't match I still want to make new myOtherModel but with an empty string for the missing value then add all those new myOtherModel will be added to a list.
The new myModel object will be one of two scenarios
For example: Dict1.Keys = 1,2,3,4....100. Dict2.Keys = 5,9,27,55
myList.Add(new myModel = {1, "", someModel[]}) //did not find a match
myList.Add(new myModel = {5, dict2.MatchingValue, someModel[]}) // did find a match
So basically, compare two dictionaries, for each item in the larger dictionary, make a new myModel with the item's values (one of them will be empty). But if that item's key matches a key in the other dictionary, grab the second dictionary's value and slap that in the new myModel
I tried messing around with a Tuples but I wasn't able to manipulate them how I wanted to.
This is what I have so far, but instead of giving me 490 items (the count from dict1) I get the 44k (the amount of the two being multiplied together)
foreach (var pair in dict1)
{
foreach (var item in dict2)
{
if (item.Key == pair.Key)
{
var x = new myModel()
{
prop1 = item.Value,
prop2 = pair.Key,
prop3 = pair.Value
};
myListOfModels.add(x);
}
else
{
var x = new myModel()
{
prop1 = "",
prop2 = pair.Key,
prop3 = pair.Value
};
myListOfModels.add(x);
}
}
}
You're looping through the second collection each time you iterate through the first collection which is why you're seeing too many results. You can easily simplify your code with a simple bit of Linq...
foreach (var pair in dict1)
{
// Get the matched value. If there isn't one it should return the default value for a string.
var matchedValue = dict2.Where(x => x.Key == pair.Key).Select(x => x.Value).SingleOrDefault();
var x = new myModel()
{
prop1 = matchedValue,
prop2 = pair.Key,
prop3 = pair.Value
};
myListOfModels.add(x);
}

Categories

Resources