How to modify a specific item in a collection usin

2019-08-04 09:46发布

问题:

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 });                              
    }

}

回答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.



回答2:

collection.GetType().GetProperty("Item").SetValue(collection, o, new object[] { 1 })


回答3:

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;
});


回答4:

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;
    }


标签: c# reflection