I have an item in a collection I need to modify using reflection - I'm using reflection because I don't know the exact type of the generic collection until runtime.
I know how to use the SetValue() method to set the value of a property retrieved through collection, but can I use SetValue() to set an actual object inside a collection?
IEnumerable businessObjectCollection = businessObject as IEnumerable;
foreach (Object o in businessObjectCollection)
{
// I want to set the "o" here to some replacement object in the collection if
// a property on the object equals something
Type t = o.GetType();
PropertyInfo identifierProperty = o.GetType().GetProperty("Identifier");
long entityID = (long)identifierProperty.GetValue(o, null);
if (replacementEntity.Identifier == entityID)
{
// IN THIS CASE: set "o" to be the replacementEntity object
// defined somewhere else.
// I can retrieve the object itself using this code, but
// would I set the object with SetValue?
object item = businessObjectCollection.GetType().GetMethod("get_Item").Invoke(businessObjectCollection, new object[] { 1 });
}
}
Well, you use get_Item
to retrieve it so you should be able to call set_Item
to set it:
businessObjectCollection.GetType().GetMethod("set_Item").Invoke(businessObjectCollection, new object[] { 1, replacementEntity });
Note that this will explode if the collection is not of a type supporting indexed access.
collection.GetType().GetProperty("Item").SetValue(collection, o, new object[] { 1 })
Rather than attempt to modify the enumerable, you could replace it with a new enumerable that performs the replacement inline. It really depends what you're doing with it afterwards though so YMMV.
IEnumerable newCollection = businessObjectCollection.Cast<object>().Select((o) =>
{
Type t = o.GetType();
PropertyInfo identifierProperty = o.GetType().GetProperty("Identifier");
long entityID = (long)identifierProperty.GetValue(o, null);
if (replacementEntity.Identifier == entityID)
{
return replacementEntity;
}
return o;
});
This method adds an object to a collection property of said objects on an object.
obj is the Parent object which contains a property Collection
propertyName is the name of the Collection property
value is the object that is to be added to the Collection
private object AddItemToCollectionProperty( Object obj, string propertyName, Object value )
{
PropertyInfo prop = obj.GetType().GetProperty( propertyName );
if( prop != null )
{
try
{
MethodInfo addMethod = prop.PropertyType.GetMethod( "Add" );
if(addMethod ==null)
{
return obj;
}
addMethod.Invoke( prop.GetValue(obj), new object [] { value } );
}
catch( Exception ex )
{
Debug.Write( $"Error setting {propertyName} Property Value: {value} Ex: {ex.Message}" );
}
}
else
{
Debug.Write( $"{propertyName} Property not found: {value}" );
}
return obj;
}