I'm new to C#, long time C++ programmer, im just wondering once initalising a propertygrid using .selectedObjects. Is there a way to get contents of the current values in the propertygrid.
Ben
PropertyGrid doesn't expose its internals to the consumer.
However, .Net lets you perform "Refelction" to examine the structure (and execute parts of) code, including class properties.
Here is an article that covers the basics of reflection. You can actually see more of the internals with reflection than what the property grid displays.
You have to iterate through all the properties of the object in the grid, using Reflection based in the object's type.
object o = PropertyGrid.SelectedObject;
Type t = o.GetType(); // We will work on type "t"
List<MemberInfo> members = new List<MemberInfo>();
members.AddRange(t.GetProperties(BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Instance); // Get the public instance properties list
foreach (MemberInfo member in members)
{
Type type = null;
object value = null;
PropertyInfo pi = (member as PropertyInfo);
type = pi.PropertyType;
if (type.IsSubclassOf(typeof(CollectionBase)))
continue; // Sorry
if (pi.GetCustomAttributes(typeof(NotSerializedAttribute), true).GetLength(0) > 0)
continue;
if (!pi.CanRead || !pi.CanWrite)
continue;
value = pi.GetValue(o, null);
// TODO Print out, or save the "value"
}
Related
I have the following loop over a dictionary type collection
foreach(KeyValuePair<Vector2, Object> entry in v_map.map_set)
{
}
I want to access the object properties, but the expected syntax doesn't work. E.G:
foreach(KeyValuePair<Vector2, Object> entry in v_map.map_set)
{
Object ob = entry.Value;
ob.property;
}
Fails because C# can't find the property wanted.
So, how do I access the desired properties?
solution:
foreach(KeyValuePair<Vector2, Object> entry in v_map.map_set)
{
if (entry.Value is warehouse)
{
warehouse ob = (warehouse)entry.Value;
}
}
If you know the type of the objects that are in the KeyValuePair, you can cast it to that type, and you will be able to find the properties you need.
And if you have several different objects stored, you can check which type it is by using is.
Like so:
if(entry.Value is Foo)
{
Foo lFoo = (Foo)entry.Value;
}
else if(entry.Value is Bar)
{
Bar lBar = (Bar)entry.Value;
}
You can make use of Refection to get the value of proerty of the object.
something like this
PropertyInfo info2 = object.GetType().GetProperty("prpertyname");
Object val = info2.GetValue(object, null);
You need to cast entry.Value to the type you need. The Object type itself isn't going to expose the properties you want.
If you just need to access the values, and you know the expected type you can use
foreach(ExpectedType value in v_map.map_set.Values.OfType<ExpectedType>())
{
var property = value.Property;
}
where Property is a property on ExpectedType.
The problem is that you're using an object which isn't typed. So you're going to need to use reflection like this:
PropertyInfo pi = ob.GetType().GetProperty("PropertyName");
var val = pi.GetValue(ob, null);
Now, if the property isn't public then you'll need to employ something else like this:
PropertyInfo pi = ob.GetType().GetProperty("PropertyName", BindingFlags.Instance | BindingFlags.NonPublic);
var val = pi.GetValue(ob, null);
Now, if this is actually a field you're trying to get to, you're going to need to do something different even yet:
FieldInfo fi = ob.GetType().GetField("fieldName");
var val = fi.GetValue(ob);
GetProperty method
BindingFlags enumeration
GetField method
I am trying to get the values from multiple properties in an entity framework object. There are 11 properties, each with a date assigned to it. I've tried using reflection but I keep getting an error " Object does not match target type"
public void CheckWeekStatus()
{
var currentFlexi = from c in FlexiContext.FlexPeriods where c.FlexiCurrentYear == true select c;
FlexPeriod s = new FlexPeriod();
PropertyInfo[] properties = s.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var info in properties)
{
var o = info.GetValue(currentFlexi,null);
}
}
FlexPeriod is the type that contains all the properties. I can loop through the properties but obviously I'm doing something wrong with the way I'm trying to access the values. Any suggestions would be appreciated.
Firstly, you can get the Type without instantiating an object:
PropertyInfo[] properties = typeof( FlexPeriod ).GetProperties( ...
The reason GetValue is failing is that currentFlexi is a collection of FlexPeriod objects ( actually an IEnumerable<FlexPeriod> ), not a single instance of FlexPeriod.
I have a class which I'm trying to run a deep copy on. One of the members of this class is 'MeshContainers' which is an instance of MeshContainerCollection.
MeshContainerCollection<> inherits from my SceneObjectCollection<> class which inherits from List<>
What I noticed is that the source object has 1 item inside the meshcontainercollection while the cloned object has 0.
When stepping through the DeepCopy process I noticed that when I try to get the fields for MeshContainerCollection, it doesn't find any.
Now MeshContainerCollection doens't have any direct fields (only inherited fields) so I thought that was the problem.
But I use:
FieldInfo[] fields = type.GetFields(BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance);
Which (afaik) should also return the private inherited members.
I have looked through the existing BindingFlags but haven't been able to figure out if there is another BindingFlag I should use to get the inherited private fields.
Could someone tell me how I can manage to do a REAL deep copy?
Deep Copy method I'm using:
private static object Process(object obj)
{
if (obj == null)
return null;
Type type = obj.GetType();
if (type.IsValueType || type == typeof(string))
{
return obj;
}
else if (type.IsArray)
{
Type elementType = Type.GetType(
type.FullName.Replace("[]", string.Empty));
var array = obj as Array;
Array copied = Array.CreateInstance(elementType, array.Length);
for (int i = 0; i < array.Length; i++)
{
copied.SetValue(Process(array.GetValue(i)), i);
}
return Convert.ChangeType(copied, obj.GetType());
}
else if (type.IsClass)
{
object toret = FormatterServices.GetUninitializedObject(obj.GetType());
FieldInfo[] fields = type.GetFields(BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance);
foreach (FieldInfo field in fields)
{
object fieldValue = field.GetValue(obj);
if (fieldValue == null)
continue;
field.SetValue(toret, Process(fieldValue));
}
return toret;
}
else
throw new ArgumentException("Unknown type");
}
EDIT1: I prefer not to do this by serialization but by reflection.
As mentioned in GetFields documentation,
private fields on base classes are not returned.
Try this method instead:
public static IEnumerable<FieldInfo> GetAllFields(this Type type)
{
IEnumerable<FieldInfo> fields = type.GetFields(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (type.BaseType == null)
return fields;
else
return GetAllFields(baseType).Concat(fields);
}
(you might want to rewrite it to avoid all the enumerables and concatenations, but you get the idea)
one of the ways that you could achieve this is by serializing the object and then deserializing it back.. write a function to do the same..
FYI, your class needs to be marked [Serializable] for this..
there are some libraries out there that do the same.. Copyable is one of them.. I would suggest not to try and reinvent the wheel rather build up on this library as there are too many edge conditions to handle when you deep copy.. may be you can submit patches to the author too..
I got this code thats works :
var assembly= Assembly.LoadFrom("D:\\...\\mydll.dll");
Type rmType = assembly.GetType(specific_class_with_namespace);
bject MyObjj = Activator.CreateInstance(rmType);
PropertyInfo[] pi = rmType.GetProperties();
foreach(PropertyInfo prop in pi)
{
Console.WriteLine("Prop: {0}", prop.Name);
}
The thing is that the property I wanna access to is a IEnumerable<IWidget>, where IWidget is an internal class of my dll. So in my current code I can't test the Type of my PropertyInfo (and cast it right ? :/)
The final objective is to access to the Name property of my IWidget. Something like :
foreach(var widget in myProperty)
{
string widgetName = widget.Name;
}
I read a couple of tutorials on the web and some questions here on SO, but none helped me for my IEnumerable<customType> problem :/
EDIT :
when I do :
PropertyInfo ItemsProperty = rmType.GetProperty("Items");
var ItemsPropertyValue = ItemsProperty.GetValue(rmType, null);
I can a XamlParseException with the "most" InnerException being "Object does not match target type"...
You can test you property for being of type IEnumerable and then in foreach loop with reflection you can access property of item with name Name.
To test for being IEnumerable you can use typeof(IEnumerable).IsAssignableFrom(prop.PropertyType) or type.GetGenericTypeDefinition() == typeof(IEnumerable<>).
EDIT:
In GetValue you should put instance not the type:
var ItemsPropertyValue = ItemsProperty.GetValue(MyObjj, null);
I have an object and I don't know its structure until runtime. So is there any way to access data from the object ?
Thanks.
PS: I can't think of any other details to provide, please ask me if this isn't enough!
Well, you can do with with reflection. For example:
public static void ShowProperties(object o)
{
if (o == null)
{
Console.WriteLine("Null: no properties");
return;
}
Type type = o.GetType();
var properties = type.GetProperties(BindingFlags.Public
| BindingFlags.Instance);
// Potentially put more filtering in here
foreach (var property in properties.Where
(p => p.CanRead && p.GetIndexParameters().Length == 0))
{
Console.WriteLine("{0}: {1}", property.Name, property.GetValue(o, null));
}
}
Look at the Type API for ways to get methods, events, fields, nested types etc.
Have a look at Reflection
You can use reflection to determine what properties, methods, and fields an object has. take a look at the methods on the Type type