Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set property on object using Func

For mock/testing purposes, I'd like to have a method that I can pass in a collection of objects of some type, a Func to select the property to update, and the value I'd like to set each property to. I want to do this without using reflection. I could also make it an extension method and wrap it for mocking, but that's for after this is solved.

Here's an example to update a property Bar for each in a List<Foo>:

public class Foo 
{
    public string Bar { get; set; }
}

// I want something like this
public List<Foo> UpdateProp_Ideal<TProperty>(List<Foo> foos, Func<Foo, TProperty> propertyFunc, TProperty valueToSet)
{
    return foos.Select(x => { propertyFunc(x)[Somehow get setter?] = valueToSet; return x; }).ToList();
}

// I could do this, but it has a broader scope (and more typing)
public List<Foo> UpdateProp(List<Foo> foos, Func<Foo, Foo> updateFunc)
{
    return foos.Select(updateFunc).ToList();
}

// Ideal call
var updatedFoos = UpdateProp_Ideal(listOfFoos, x => x.Bar, "Updated!");

// Working call
var updatedFoos = UpdateProp(listOfFoos, x => { x.Bar = "Updated!"; return x; });
like image 961
Jecoms Avatar asked Nov 01 '25 13:11

Jecoms


1 Answers

public static List<T> UpdateProp_Ideal<T, TProperty>(
    this List<T> foos, Expression<Func<T, TProperty>> propertyFunc, TProperty valueToSet)
{
    var body = Expression.MakeBinary(
        ExpressionType.Assign, propertyFunc.Body, Expression.Constant(valueToSet)
    );
    var action = Expression.Lambda<Action<T>>(body, propertyFunc.Parameters).Compile();
    foos.ForEach(action);
    return foos;
}

Usage:

var updatedFoos = UpdateProp_Ideal(listOfFoos, x => x.Bar, "Updated!");
like image 136
Slava Utesinov Avatar answered Nov 04 '25 02:11

Slava Utesinov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!