How can i cast into a ObservableCollection<object> - c#

How can i cast
from ObservableCollection<TabItem> into ObservableCollection<object>
this doesnt work for me
(ObservableCollection<object>)myTabItemObservableCollection

you should copy like this
return new ObservableCollection<object>(myTabItemObservableCollection);

Basically, you can't. Not now, and not in .NET 4.0.
What is the context here? What do you need? LINQ has Cast<T> which can get you the data as a sequence, or there are some tricks with generic methods (i.e. Foo<T>(ObservalbleCollection<T> col) etc).
Or you can just use the non-generic IList?
IList untyped = myTypedCollection;
untyped.Add(someRandomObject); // hope it works...

you could use IEnumerable.Cast<T>()

You can't. ObservableCollection<TabItem> does not derive from ObservableCollection<object>.
If you explain why you would want to perhaps we can point out an alternative interface you can use.

thanx for all answers, but I think I have solve this problem self with a "helpermethode".
Perhaps has any a better method or a linq statement for this.
private void ConvertTabItemObservableCollection()
{
Manager manager = this.container.Resolve<Manager>();
foreach (var tabItem in manager.ObjectCollection)
{
TabItemObservableCollection.Add((TabItem)tabItem);
}
}

None of the examples I have found have worked for me, I have cobbled together the below code and it seems to work. I have a hierarchy that is created by deserializing an XML file and I am able to loop through all the objects in the hierarchy, but you can adapt this to just loop through one ObservableCollection and get the objects as objects and not strongly typed.
I want to add a PropertyChangingEventHandler to every property in the hierarchy so that I can implement undo/redo functionality.
public static class TraversalHelper
{
public static void TraverseAndExecute(object node)
{
TraverseAndExecute(node, 0);
}
public static void TraverseAndExecute(object node, int level)
{
foreach (var property in node.GetType().GetProperties())
{
var propertyValue = node.GetType().GetProperty(property.Name).GetGetMethod().Invoke(node, null); // Get the value of the property
if (null != propertyValue)
{
Console.WriteLine("Level=" + level + " : " + property.Name + " :: " + propertyValue.GetType().Name); // For debugging
if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(ObservableCollection<>)) // Check if we are dealing with an observable collection
{
//var dummyvar = propertyValue.GetType().GetMethods(); // This was just used to see which methods I could find on the Collection
Int32 propertyValueCount = (Int32)propertyValue.GetType().GetMethod("get_Count").Invoke(propertyValue, null); // How many objects in the collection
level++;
for (int i = 0; i < propertyValueCount; i++) // Loop over all objects in the Collection
{
object properyValueObject = (object)propertyValue.GetType().GetMethod("get_Item").Invoke(propertyValue, new object[] { i }); // Get the specified object out of the Collection
TraverseAndExecute(properyValueObject, level); // Recursive call in case this object is a Collection too
}
}
}
}
}
}
The method is just called like this
TraversalHelper.TraverseAndExecute(object);
If you just want to create a collection of objects you just need this bit of code
ObservableCollection<Field> typedField = migration.FileDescriptions[0].Inbound[0].Tables[0].Table[0].Fields[0].Field; // This is the strongly typed decalaration, a collection of Field objects
object myObject = typedField; // Declare as object
Int32 propertyValueCount = (Int32)myObject.GetType().GetMethod("get_Count").Invoke(myObject, null); // How many objects in this Collection
for (int i = 0; i < propertyValueCount; i++) // Loop over all objects in the Collection
{
object properyValueObject = (object)myObject.GetType().GetMethod("get_Item").Invoke(myObject, new object[] { i }); // Get the specified object out of the Collection, in this case a Field object
// Add the object to a collection of objects, or whatever you want to do with object
}

You can Cast it as INotifyCollectionChanged;
Like:
if (myTabItemObservableCollection is INotifyCollectionChanged collection)
{
Do Stuff
}

Related

How to obtain a list of objects inside another object using reflection

Using reflection I can obtain the object properties and values for all Data Types and the objects inside this object. But if the object contains a List of other objects I am having trouble in getting the objects in the list. The list can contain any type of object.
private static void SaveObj(object obj) {
foreach (var prop in obj.GetType().GetProperties()) {
if (prop.PropertyType.Namespace == "Entities") { //It is an object
object obL = prop.GetValue(obj, null);
SaveObj(obj);
}
else if (prop.PropertyType.Name == "List`1") { //This is a list of objects
object obP = prop.GetValue(obj);
//obP has the list of objects, I can see the list in debug mode.
List<object> obL = (List<object>)prop.GetValue(obj, null);
//This line returns an exception!!
}
else {
columns += prop.Name.ToLower() + ", ";
values[i] = prop.GetValue(obj, null).ToString();
}
... // the code continues ...
}
}
The exception message returned is:
"It is not possible to convert an object of type 'System.Collections.Generic.List1[Entities.OrderItem]' to type 'System.Collections.Generic.List1[System.Object]'."
Interesting is that I can see all the objects and its contents in degug mode. In Immediate Window I can print the content of the variable obP with all the objects in the list, but how to read them?
Any ideas on how to solve this?
You can try casting it to IEnumerable and then use .Cast<object>().ToList() Like this:
IEnumerable obL = prop.GetValue(obj, null) as IEnumerable;
List<object> list = obL.Cast<object>().ToList();
Sins a List implements the ICollection interface, you could, instead of attempting to cast the returned value to a List<object>, do something like:
ICollection collection = (prop.GetValue(obj, null) as ICollection);
if (collection != null)
{
object[] array = new object[collection.Count];
collection.CopyTo(array, 0);
//if you need a list just create a new one and pass in the array: new List<object>(array);
}
As a side note, wouldn't your:
if (prop.PropertyType.Namespace == "Entities")
{
object obL = prop.GetValue(obj, null);
SaveObj(obj);
}
just cause a infinite loop, which will lead to a StackOverflow/OutOfMemory exception, might want to change it to SaveObj(obL); if that was the intended behavior.

receive and use any type of ObservableCollection<T>

I met a trouble.
I want to receive any collection, type of ObservableCollection and use it.
For example, there is a class like following
public class Car{
int num;
string str;
}
and ObservableCollection
ObservableCollection<Car> carOC = new ObservableCollection<Car>();
The really important point is that actually I don't know the exist of it. I don't know what the type, T, of ObservableCollection<T>.
What I want to make is a method for showing list of properties of received ObservableCollection<T> like following
void showingProperties(ObservableCollection<T> coll)
{
foreach (T item in coll){
// showing item's property list
}
}
and if I use this method for carOC
showingProperties(carOC);
the output is
carOC has properties
num type int32
str type string
I don't know really anything to receive ObservableCollection<T> and use it...
Thanks for reading it.
In fact your problem hasn't to do anything with an ObservableCollection<T>. You could do the same with any generic collection. Just for clarify, ObservableCollection<T> observes your list and items, so that it will give you information about changings in the List. It won't observe your class structure. It doesn't make much sense to do this on a List, because your T will exist serveral times in your list, but the Information will be the same for each object. So i would recommend a Method which give you such information for a type. See it type based not object based.
public string ShowProperties<T>() : where T : class
{
var props = typeof (T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
string typeInfo = typeof (T).FullName + Environment.NewLine;
foreach (var prop in props)
{
typeInfo += prop.Name + " " + prop.PropertyType.FullName + Environment.NewLine;
}
return typeInfo;
}
If you have different items in your List, because of inheritance call this serveral times in your foreach loop. But be carefull reflection is slow if you use it in loops. Think about caching then.

Accessing elements in C# dictionary

I am a newbie currently translating C++ code to C#. I have a map
map<string, Object*> table;
and a function
void define(const string& symbol, Object* definition)
{
map<string, Object*>::iterator iter = table.find(symbol);//returns iterator to element with key "symbol," else sets equal to map::end
if (iter != table.end())//if key is in map
{
delete (*iter).second;
table.erase(iter);
}
table.insert(pair<string, Object*>(symbol,definition->clone()));
}
and I want to create the equivalent function in C#. I've created a Dictionary:
private Dictionary<string, Object> table = new Dictionary<string, Object>();
and here is my function so far
public void define(string symbol, Object definition)
{
if (table.ContainsKey(symbol))
{
//function body
}
and now need my function body to accomplish the same thing. From my research, it doesn't seem like C# has the same iterator structure.
Your method in the end replaces an element (if present), or adds it... In C# you can simply:
public void define(string symbol, Object definition)
{
table[symbol] = definition;
}
Note that if definition can be IDisposable and you have ownership of it, then it would be better to Dispose() it, in a similar manner to the one used in C++
public void define(string symbol, Object definition)
{
object oldDefinition;
if (table.TryGetValue(symbol, out oldDefinition) && oldDefinition != null)
{
IDisposable disp = oldDefinition as IDisposable;
if (disp != null)
{
disp.Dispose();
}
}
table[symbol] = definition;
}
For the clone()
You have to choose how to handle the clone(). Being references even in C++, it is a little strange that they chosed to clone() the Object. If you want to clone() it, clearly you'll need to expose a method for your CloneableObject to clone it. Note that Object (or object) in C# isn't cloneable "out of the box". You have to write the code to clone it.
If I understand correctly, you need an iterator over dictionary in c#. You can use one of the following way to iterate over dictionary in c#
foreach(var pair in table)
{
var key = pair.Key;
var value = pair.Value;
}
or
foreach(KeyValuePair<string, Object> entry in table)
{
// do something with entry.Value or entry.Key
}
or
for (int index = 0; index < table.Count; index++) {
var item = table.ElementAt(index);
var itemKey = item.Key;
var itemValue = item.Value;
}
You can add if clause in foreach loop and process it.

Removing objects from a bindinglist bound to a datagrid view

I'm trying to remove objects from a BindingList that is bound to a DataGridView by doing this...
private void RemoveItems(List<Payment> removeList)
{
for (int i = removeList.Count - 1; i >= 0; i--)
{
sortableBindingPaymentList.Remove(removeList[i]);
}
}
Trying to debug this myself i attempted the following, however remover always = -1 (meaning that no match was found) and I'm 110% sure that my list of Payment's in removeList contains a match in my sortableBindingList...
private void RemoveItems(List<Payment> removeList)
{
int remover;
for (int i = removeList.Count - 1; i >= 0; i--)
{
remover = sortableBindingPaymentList.IndexOf(removerList[i]);
sortableBindingPaymentList.RemoveAt(remover);
}
}
Any help is appreciated and thanks in advance!
I'm not sure I would go the IEquatable way.. depending on the ORM you're using that might bring you some trouble.
Do your entities have a primary key? you can try this instead:
private void RemoveItems(List<Payment> removeList)
{
removeList.ForEach(x => sortableBindingPaymentList.RemoveAll(s => s.Id == x.Id));
}
P.S: I strongly suggest you to start using LinQ for these kind of operations instead of for loops.
if removeList doesn't contain the same references (same objects) as the ones in sortableBindingPaymentList then the method will return -1, which i assume happens in your case.
It states here:
that the "Remove" method of a list:
"This method determines equality using the default equality comparer EqualityComparer.Default for T, the type of values in the list."
Payment class should implement IEquatable interface.
Eg:
public class Payment : IEquatable
{
public bool Equals(Payment paymentObj)
{
//is current instance equal to payment OBJ?
//if yes, then return true otherwise false
}
}
Now this call should work even if you have different instances of objects in list collections.
sortableBindingPaymentList.Remove(removeList[i]);
Please post complete post if you need further help.

Accessing a Collection Through Reflection

Is there a way to iterate (through foreach preferably) over a collection using reflection? I'm iterating over the properties in an object using reflection, and when the program gets to a type that is a collection, I'd like it to iterate over the contents of the collection and be able to access the objects in the collection.
At the moment I have an attribute set on all of my properties, with an IsCollection flag set to true on the properties that are collections. My code checks for this flag and if it's true, it gets the Type using reflection. Is there a way to invoke GetEnumerator or Items somehow on a collection to be able to iterate over the items?
I had this issue, but instead of using reflection, i ended up just checking if it was IEnumerable. All collections implement that.
if (item is IEnumerable)
{
foreach (object o in (item as IEnumerable))
{
}
} else {
// reflect over item
}
I've tried to use a similar technique as Darren suggested, however just beware that not just collections implement IEnumerable. string for instance is also IEnumerable and will iterate over the characters.
Here's a small function I'm using to determine if an object is a collection (which will be enumerable as well since ICollection is also IEnumerable).
public bool isCollection(object o)
{
return typeof(ICollection).IsAssignableFrom(o.GetType())
|| typeof(ICollection<>).IsAssignableFrom(o.GetType());
}
Just get the value of the property and then cast it into an IEnumerable. Here is some (untested) code to give you an idea:
ClassWithListProperty obj = new ClassWithListProperty();
obj.List.Add(1);
obj.List.Add(2);
obj.List.Add(3);
Type type = obj.GetType();
PropertyInfo listProperty = type.GetProperty("List", BindingFlags.Public);
IEnumerable listObject = (IEnumerable) listProperty.GetValue(obj, null);
foreach (int i in listObject)
Console.Write(i); // should print out 123
Just for information may be it will be of someone's help...
I had a class with nested classes and collection of some other classes. I wanted to save the property values of the class as well nested classes and collection of classes. My code is as follows:
public void LogObject(object obj, int indent)
{
if (obj == null) return;
string indentString = new string(' ', indent);
Type objType = obj.GetType();
PropertyInfo[] properties = objType.GetProperties();
foreach (PropertyInfo property in properties)
{
Type tColl = typeof(ICollection<>);
Type t = property.PropertyType;
string name = property.Name;
object propValue = property.GetValue(obj, null);
//check for nested classes as properties
if (property.PropertyType.Assembly == objType.Assembly)
{
string _result = string.Format("{0}{1}:", indentString, property.Name);
log.Info(_result);
LogObject(propValue, indent + 2);
}
else
{
string _result = string.Format("{0}{1}: {2}", indentString, property.Name, propValue);
log.Info(_result);
}
//check for collection
if (t.IsGenericType && tColl.IsAssignableFrom(t.GetGenericTypeDefinition()) ||
t.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == tColl))
{
//var get = property.GetGetMethod();
IEnumerable listObject = (IEnumerable)property.GetValue(obj, null);
if (listObject != null)
{
foreach (object o in listObject)
{
LogObject(o, indent + 2);
}
}
}
}
}
An called this function
LogObject(obj, 0);
However, I have some structs inside my classes and I need to figure out how to get their values. Moreoevr, I have some LIst. I need to get their value as well.... I will post if I update my code.
The best you could probably do would be to check if the object implements certain collection interfaces - probably IEnumerable would be all that you need. Then it's just a matter of calling GetEnumerator() off of the object, and using IEnumerator.MoveNext() and IEnumerator.Current to work your way through the collection.
This won't help you if the collection doesn't implement those interfaces, but if that's the case it's not really much of a collection, I suppose.
When your using reflection you aren't necessarily using an instance of that object. You would have to create an instance of that type of be able to iterate through the object's properties. So if you are using reflection use the ConstructorInfo.Invoke() (?) method to create a new instance or point to an instance of the type.
I would look at the Type.FindInterfaces method. This can filter out the interfaces implemented by a given type. As in PropertyInfo.PropertyType.FindInterfaces(filterMethod, filterObjects). You can filter by IEnumerable and see if any results are returned. MSDN has a great example in the method documentation.
If you're not using an instance of the object but rather a Type, you can use the following:
// type is IEnumerable
if (type.GetInterface("IEnumerable") != null)
{
}
A rather straightforward approach would be to type cast the object as the collection and directly use that.

Categories

Resources