Get all data from the object into one two-dimentional array - c#

I need to dump all data from the object into two-dimetional array
this is the declaration:
GetItemCall oGetItemCall = new GetItemCall(oContext);
then, I can use oGetItemCall.Item.ConditionID or oGetItemCall.Item.ListingDetails.EndTime etc.
But the oGetItemCall object has lots of variables and I want to add them into one easy to read 2-dimensional array.
Is there any way of doing this ?

Array is required?
Why don't use a more flexible structure, like list. So try to convert object to list. A list can be easily accessed through indexes: in this case through the object's properties names.
Reflection can solve the problem.
Have a look here.

It's not clear why you would want to do that, however either one of those should do.
string[,] some = new string[100,2];
Hashtable table = new Hashtable();
// array
some[0,0] = "Key";
some[0,1] = "value";
// hashtable
table["key"] = "value";

So you want to look at the item and all of it's properties and values? Use reflection.
It is not perfect and by no means complete - but will give you a good starting point if this is what you want. Easily extendible to add type names, etc.
public static List<string> ReflectObject(object o)
{
var items = new List<string>();
if (o == null)
{
items.Add("NULL"); // remove if you're not interested in NULLs.
return items;
}
Type type = o.GetType();
if (type.IsPrimitive || o is string)
{
items.Add(o.ToString());
return items;
}
items.Add(string.Format("{0}{1}{0}", " ----- ", type.Name));
if (o is IEnumerable)
{
IEnumerable collection = (IEnumerable)o;
var enumerator = collection.GetEnumerator();
while (enumerator.MoveNext())
{
foreach (var innerItem in ReflectObject(enumerator.Current))
{
items.Add(innerItem);
}
}
}
else
{
var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
foreach (var property in properties)
{
object value = property.GetValue(o, null);
foreach (var innerItem in ReflectObject(value))
{
items.Add(string.Format("{0}: {1}", property.Name, innerItem));
}
}
}
return items;
}
It can be used like this:
Test t = new Test();
t.MyProperty1 = 123;
t.MyProperty2 = "hello";
t.MyProperty3 = new List<string>() { "one", "two" };
t.MyTestProperty = new Test();
t.MyTestProperty.MyProperty1 = 987;
t.MyTestProperty.MyTestProperty = new Test();
t.MyTestProperty.MyTestProperty.MyProperty2 = "goodbye";
var items = MyReflector.ReflectObject(t);
foreach (var item in items)
{
Console.WriteLine(item);
}
This would result in:
----- Test -----
MyProperty1: 123
MyProperty2: hello
MyProperty3: ----- List`1 -----
MyProperty3: one
MyProperty3: two
MyTestProperty: ----- Test -----
MyTestProperty: MyProperty1: 987
MyTestProperty: MyProperty2: NULL
MyTestProperty: MyProperty3: NULL
MyTestProperty: MyTestProperty: ----- Test -----
MyTestProperty: MyTestProperty: MyProperty1: 0
MyTestProperty: MyTestProperty: MyProperty2: goodbye
MyTestProperty: MyTestProperty: MyProperty3: NULL
MyTestProperty: MyTestProperty: MyTestProperty: NULL

Related

creating IList<T> values at runtime from variables

Im getting data from a solaceconnection which returns data as so {Account:"023": hasAccount:true} and I need to break it up and put it into two list (IList names and IList values). Names will be "Account" and "hasAccount" which I am able to do. But, Im having a problem with values. I am trying to get the type of the values ("023" and true in this example) and creating IList of type string" for "023" and IList of type bool for true. I have been trying the below but
Cache.ToList().ForEach(row => {
List<string> _namesList = new List<string>();
List<object> _valuesList = new List<object>();
FieldInfo[] fields = row.GetType().GetFields(BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance);
fields.ToList().ForEach(field => {
var fieldName = field.Name;
var fieldValue = field.GetValue(row);
_namesList.Add(fieldName);
var m_oEnum = Activator.CreateInstance(fieldValue.GetType(), new object[] { 1 }); // Length 1
//var m_oEnum = new propertyType[] { fieldValue };
_valuesList.Add(m_oEnum);
});
});
My intentions with var m_oEnum is to create a IList or array of type stirng or bool and set the fieldvalue in it. But Im not able to do it since i get the exception thrown "Constructor on type 'System.Boolean' not found." for line
var m_oEnum = Activator.CreateInstance(objectType, new object[] { 1 }); // Length 1
is it possible to create an array on the fly with a datatype and place the value in it? Thanks
Value types should be handled differently.
Cache.ToList().ForEach(row => {
List<string> _namesList = new List<string>();
List<object> _valuesList = new List<object>();
FieldInfo[] fields = row.GetType().GetFields(BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance);
fields.ToList().ForEach(field => {
var fieldName = field.Name;
var fieldValue = field.GetValue(row);
_namesList.Add(fieldName);
var objectType = fieldValue.GetType();
if (objectType.IsValueType)
{
_valuesList.Add(fieldValue);
}
else
{ // What about types without a parameterless constructor?
var m_oEnum = Activator.CreateInstance(objectType, new object[] { 1 }); // Length 1
_valuesList.Add(m_oEnum);
}
});
});

How to access properties of the object type c#?

var obj1 = new A()
{
Name = "abc",
Id = 1
}
var obj2 = new B()
{
Place = "XYZ",
Pincode = 123456
}
var obj3 = new C()
{
Mark = 100,
Standard = "Tenth"
}
var myList = new List<object>();
myList .add(obj1);
myList .add(obj2);
myList .add(obj3);
This is my code structure. I need to access the properties of the myList object. i.e) I need to access the properties like Name, Id, Place, Pincode, Mark, Standard from the myList object and it's corresponding values.
How to achieve it?
As I wrote in my comment, usually keeping completely different types in the same collection is wrong. However, that doesn't mean that's always the case, and so assuming you have a good enough reason to do that - here's one option to do it.
Assuming c# 7 or higher, your best option would probably be to (ab)use switch with pattern matching:
foreach(var obj in myList)
{
switch(obj)
{
case A a:
DoSomethingWithA(a);
break;
case B b:
DoSomethingWithB(b);
break;
}
}
You can try something like below. Working code here
public static List<List<string>> GetProperties(List<object> myList)
{
// If you don't want two lists, you can use Dictionary<key, value>
List<string> props = new List<string>();
List<string> values = new List<string>();
foreach (var a in myList)
{
if(a == null)
continue;
var propsInfo = a.GetType().GetProperties();
foreach (var prop in propsInfo)
{
if(!props.Contains(prop.Name))
{
props.Add(prop.Name);
values.Add(prop.GetValue(a, null).ToString());
}
}
}
return new List<List<string>> { props, values};
}
If you are simply looking to get values out of an object (property values), that is a different story.
foreach (objectType obj in mylist)
{
someVariable1 = obj.name;
someVariable2 = obj.Id;
}
Here is some code I use to compare two objects. I don't know if this is your scenario but I hope it helps you get what you need it for.
protected List<string> GetProperties(List<object> myList)
{
List<string> props = new List<string>();
foreach (var a in myList)
{
if(a == null)
continue;
var propsInfo = a.GetType().GetProperties();
foreach (var prop in propsInfo)
{
if(!props.Contains(prop.Name))
{
props.Add(prop.Name);
}
}
}
return props;
}

How do you iterate through a mixed List<t> and print contents to console in C#?

I have a List<object> which contains strings and even additional lists.
List<object> NewArray = new List<object>();
so basically the list contains a mixture....
As a sanity check, I want to print out the contents to the console. I start by iterating through and test to see whether the element is a list. If it isn't then it will be a string and can be printed to the console. If it is a list, I want to iterate through and print the string contents to the console but with a tab to indent it.
I have this so far:
for (int outer = 0; outer < NewArray.Count; outer++)
{
var innerList = NewArray[outer];
if (innerList.GetType().IsGenericType && innerList.GetType().GetGenericTypeDefinition() == typeof(List<>))
{
for (int inner = 0; inner < innerList.Count; inner++)
{
//print string
}
}
else
{
//print string
}
}
I didn't want to use a foreach loop as I'm not sure the order of the list would be guaranteed and will be in the future adding a increment number (which can be provided by the inner and outer variables).
The issue I am getting is an error here:
inner < innerList.Count
which is:
Operator '<' cannot be applied to operands of type 'int' and 'method group'
What do I need to do to overcome this? I'm not sure it is the most efficient way of achieving the end result but....
static void Main()
{
var randomCrap = new List<Object>
{
1, "two",
new List<object> { 3, 4 },
5, 6,
new List<object> {
new List<object> { 7, 8, "nine" },
},
};
randomCrap.PrintAll();
}
Output:
1
two
3
4
5
6
7
8
nine
Using this:
public static class Extensions
{
public static void PrintAll(this Object root)
{
foreach (var x in root.SelectAll())
{
Console.WriteLine(x);
}
}
public static IEnumerable<Object> SelectAll(this object o)
{
// Thank you, eocron
if (o is String)
{
yield return o;
}
else if (o is IEnumerable)
{
var e = o as IEnumerable;
foreach (var child in e)
{
foreach (var child2 in child.SelectAll())
yield return child2;
}
}
else
{
yield return o;
}
}
}
If you know your object is a List<> of some generic type, you could always cast to IList and loop through it that way.
To paraphrase your code:
if (innerList.GetType().IsGenericType && innerList.GetType().GetGenericTypeDefinition() == typeof(List<>))
{
var list = (IList)innerList;
for (int inner = 0; inner < list.Count; inner++)
{
Console.WriteLine(list[inner].ToString());
//print string
}
}
But in reality, you should be doing what itsme86 said, and making strong types with an overriden ToString() or Display() method.
Here is more simplistic way of doing what you want:
public static void DeepPrint(object obj, int recursionLevel)
{
if(obj == null)
{
//print null
return;
}
var str = obj as string;
if(str != null)
{
//print str
return;
}
var enumer = obj as IEnumerable;
if(enumer != null)
{
foreach(var e in enumer)
{
DeepPrint(e, recursionLevel+1);
}
return;
}
//print obj.ToString();
}
Then call it like this on whatever you desire:
DeepPrint(myObjectOrList, 0);
PS
For those who say about "random crap" - embrace the string.Format(...), embrace serialization in general, embrace WCF and dynamic, and etc. There is many random things in this world, what doesn't really need strong typing. In fact it will just become "crap" if you provide strong typing to some common used functions.
One way you could do it is to check if the object implements ICollection, and if so, iterate over the contents. I created a recursive method to handle cases where a collection contained other collections, which includes an indentAmount argument, so that nested collections are indented by a tab each time they're encountered:
public static void PrintItem(object item, int indentAmount = 0)
{
var indent = new string('\t', indentAmount);
if (item == null) Console.WriteLine($"{indent}<null>");
if (item is ICollection)
{
var innerItems = item as IEnumerable;
Console.WriteLine($"{indent}Collection type encountered:");
indentAmount++;
foreach (var innerItem in innerItems)
{
PrintItem(innerItem, indentAmount);
}
}
else
{
Console.WriteLine($"{indent}{item}");
}
}
Usage
private static void Main()
{
var items = new List<object>
{
"first",
2,
new List<string> {"listFirst", "listSecond"},
new[] {"arrayFirst", "arraySecond"},
new ArrayList {"arrayListFirst", "arrayListSecond"},
"third",
new List<List<string>>
{
new List<string> {"nestedList1First", "nestedList1Second"},
new List<string> {"nestedList2First", "nestedList2Second"}
},
4f,
new object[] {5d, "six", new List<object>{"seven", 8} },
9,
"ten"
};
PrintItem(items);
Console.WriteLine("\nDone!\nPress any key to exit...");
Console.ReadKey();
}
Output

NHibernate AliasToBean transformer associations

I'm trying to use the following statement to get an entity with the fields I'm after:
retVal = session.CreateCriteria(typeof(MyEntity))
.CreateAlias("MyEntityProperty", "MyEntityProperty")
.Add(Restrictions.Eq("MyEntityProperty.Year", year))
.SetProjection(
Projections.Distinct(
Projections.ProjectionList()
.Add(Projections.Property("Property1"), "Property1")
.Add(Projections.Property("Property2"), "Property2")
.Add(Projections.Property("MyEntityProperty.RegisteredUser"), "MyEntityProperty.RegisteredUser")
.Add(Projections.Property("MyEntityProperty.CompanyInfo"), "MyEntityProperty.CompanyInfo")
)
)
.SetResultTransformer(Transformers.AliasToBean(typeof(MyEntity)))
.List<MyEntity>()
.Cast<BaseMyEntity>();
MyEntity is the entity I want to return, and MyEntityProperty is a property of MyEntity that is another entity (of type MyEntityProperty).
The error I get is Could not find a setter for property 'MyEntityProperty.RegisteredUser' in class 'MyEntity'
Is the AliasToBean transformer not able to handle sub entities? Or is there something more I need to do to make it work?
There is my master piece... which I'm using to transform any level of projections depth. Take it and use it like this:
.SetResultTransformer(new DeepTransformer<MyEntity>())
It could be used for any ValueType properties, many-to-one references and also for dynamic objects...
public class DeepTransformer<TEntity> : IResultTransformer
where TEntity : class
{
// rows iterator
public object TransformTuple(object[] tuple, string[] aliases)
{
var list = new List<string>(aliases);
var propertyAliases = new List<string>(list);
var complexAliases = new List<string>();
for(var i = 0; i < list.Count; i++)
{
var aliase = list[i];
// Aliase with the '.' represents complex IPersistentEntity chain
if (aliase.Contains('.'))
{
complexAliases.Add(aliase);
propertyAliases[i] = null;
}
}
// be smart use what is already available
// the standard properties string, valueTypes
var result = Transformers
.AliasToBean<TEntity>()
.TransformTuple(tuple, propertyAliases.ToArray());
TransformPersistentChain(tuple, complexAliases, result, list);
return result;
}
/// <summary>Iterates the Path Client.Address.City.Code </summary>
protected virtual void TransformPersistentChain(object[] tuple
, List<string> complexAliases, object result, List<string> list)
{
var entity = result as TEntity;
foreach (var aliase in complexAliases)
{
// the value in a tuple by index of current Aliase
var index = list.IndexOf(aliase);
var value = tuple[index];
if (value.IsNull())
{
continue;
}
// split the Path into separated parts
var parts = aliase.Split('.');
var name = parts[0];
var propertyInfo = entity.GetType()
.GetProperty(name, BindingFlags.NonPublic
| BindingFlags.Instance
| BindingFlags.Public);
object currentObject = entity;
var current = 1;
while (current < parts.Length)
{
name = parts[current];
object instance = propertyInfo.GetValue(currentObject);
if (instance.IsNull())
{
instance = Activator.CreateInstance(propertyInfo.PropertyType);
propertyInfo.SetValue(currentObject, instance);
}
propertyInfo = propertyInfo.PropertyType.GetProperty(name, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
currentObject = instance;
current++;
}
// even dynamic objects could be injected this way
var dictionary = currentObject as IDictionary;
if (dictionary.Is())
{
dictionary[name] = value;
}
else
{
propertyInfo.SetValue(currentObject, value);
}
}
}
// convert to DISTINCT list with populated Fields
public System.Collections.IList TransformList(System.Collections.IList collection)
{
var results = Transformers.AliasToBean<TEntity>().TransformList(collection);
return results;
}
}
Well wasn't I making things more complicated than necessary.
Instead of trying to set the fields on the sub entity, all I needed to do was reference the entity field itself:
.Add(Projections.Property("MyEntityProperty"), "MyEntityProperty")
and nHibernate populated it fine.
But I'm glad I asked because I got Radim's very useful code :-)

C# how to output all the items in a class(struct) [duplicate]

This question already has answers here:
What is the best way to dump entire objects to a log in C#?
(16 answers)
Closed 8 years ago.
i have class basically just a row of a table.
this row contains many columns.
for testing purpose, i will need to output the reads i get .
so i need to output all of the columns in the row.
the class is like
public class tableRow
{
public tableRow()
{}
public string id
public string name
public string reg
public string data1
....
....
....
<lot more columns>
}
then i need to write like:
Console.WriteLine("id: " + tableRow.id);
Console.WriteLine("name: " + tableRow.name);
Console.WriteLine("reg: " + tableRow.reg);
Console.WriteLine("data1: " + tableRow.data1);
...
...
...
<lot more Console.WriteLine>
So i want to know , is there an easy way to get all of these output , without so much console.writeLine?
thanks
You can serialize tableRow into JSON and all columns will be printed. E.g. with JSON.NET (available from NuGet):
tableRow tr = new tableRow { id = "42", name = "Bob", reg = "Foo" };
Console.WriteLine(JsonConvert.SerializeObject(tr, Formatting.Indented));
Output:
{
"id": "42",
"name": "Bob",
"reg": "Foo",
"data1": null
}
I use this approach for logging (to show object state) - it's nice to have extension
public static string ToJson<T>(this T obj)
{
return JsonConvert.SerializeObject(tr, Formatting.Indented);
}
Usage is simple:
Console.WriteLine(tr.ToJson());
Here's a short example using reflection:
void Main()
{
var myObj = new SomeClass();
PrintProperties(myObj);
myObj.test = "haha";
PrintProperties(myObj);
}
private void PrintProperties(SomeClass myObj){
foreach(var prop in myObj.GetType().GetProperties()){
Console.WriteLine (prop.Name + ": " + prop.GetValue(myObj, null));
}
foreach(var field in myObj.GetType().GetFields()){
Console.WriteLine (field.Name + ": " + field.GetValue(myObj));
}
}
public class SomeClass {
public string test {get; set; }
public string test2 {get; set; }
public int test3 {get;set;}
public int test4;
}
Output:
test:
test2:
test3: 0
test4: 0
test: haha
test2:
test3: 0
test4: 0
This should work for classes as well as types with custom type descriptors:
private static void Dump(object o)
{
if (o == null)
{
Console.WriteLine("<null>");
return;
}
var type = o.GetType();
var properties = TypeDescriptor.GetProperties(type);
Console.Write('{');
Console.Write(type.Name);
if (properties.Count != 0)
{
Console.Write(' ');
for (int i = 0, n = properties.Count; i < n; i++)
{
if (i != 0)
Console.Write("; ");
var property = properties[i];
Console.Write(property.Name);
Console.Write(" = ");
Console.Write(property.GetValue(o));
}
}
Console.WriteLine('}');
}
If you want to dump fields, and not properties, you can use type.GetFields() and make the necessary modifications to the above code. FieldInfo has a similar GetValue() method.
Note that this will not print "deep" representations of records. For that, you could adapt this into a recursive solution. You may also want to support collections/arrays, quote strings, and identify circular references.
You could use reflection, to do it ... Give me a minute, I'll post some code
Something along:
PropertyInfo[] propertyInfos;
propertyInfos = typeof(MyClass).GetProperties(BindingFlags.Public |
BindingFlags.Static);
// sort properties by name
Array.Sort(propertyInfos,
delegate(PropertyInfo propertyInfo1, PropertyInfo propertyInfo2)
{ return propertyInfo1.Name.CompareTo(propertyInfo2.Name); });
// write property names
foreach (PropertyInfo propertyInfo in propertyInfos)
{
Console.WriteLine(propertyInfo.Name);
}
You could add a check to see it's a string, and add some output as well, but that's the git of it.
Source from here
if you set up an array of strings
var dataFields = new string[] { "id", "name", ...
you could do a foreach loop to populate the table, and reference the table data using the same array, allowing you to do another foreach loop to do the Console.WriteLine calls
If you wanted to, each table row could just be a dictionary, with the datafield as the key, and the data as a value. Then you can just loop though the dictionary

Categories