Delegate that selects a writable property on a generic
Yup, it is possible, but you'll have to delve into the dark world of Expression Trees.

This function creates getter and setter functions using the out parameters. It's ugly, and you usually don't want to use two out parameters, but hopefully it'll get you moving in the right direction.

public static bool CreateGetterSetter&lt;T, V&gt;(Expression&lt;Func&lt;T, V&gt;&gt; getterExpression, out Func&lt;T, V&gt; getter, out Action&lt;T, V&gt; setter)
{
    if (getterExpression == null)
        throw new ArgumentNullException("getterExpression");

    var memberExpression = getterExpression.Body as MemberExpression;
    if (memberExpression == null || memberExpression.NodeType != ExpressionType.MemberAccess || memberExpression.Member == null)
        throw new ArgumentException("The expression must get a member (property or field).", "getterExpression");

    // The expression passed in is the getter, so just compile it.
    getter = getterExpression.Compile();

    // The setter function takes two parameters as input.
    var paramT = Expression.Parameter(typeof(T));
    var paramV = Expression.Parameter(typeof(V));

    // Create the setter function
    if (memberExpression.Member.MemberType == MemberTypes.Field)
    {
        // The getter retrieves a field. 
        var field = memberExpression.Member as FieldInfo;
        if (field == null)
            throw new ArgumentException("Could not get field info for member " + memberExpression.Member.ToString());

        // This expression represents the field on the parameter.
        var fieldExpr = Expression.Field(paramT, field);

        // This expression is what the field will be set to.
        Expression rightExpr;
        if (paramV.Type == field.FieldType)
            rightExpr = paramV;
        else
            rightExpr = Expression.Convert(paramV, field.FieldType);

        // This is the assignment expression (sets the field to the parameter value).
        var assign = Expression.Assign(fieldExpr, rightExpr);

        // Compile the expressions into a lambda.
        setter = Expression.Lambda&lt;Action&lt;T, V&gt;&gt;(assign, paramT, paramV).Compile();
    }
    else if (memberExpression.Member.MemberType == MemberTypes.Property)
    {
        // The getter retrieves a property.
        var property = memberExpression.Member as PropertyInfo;
        if (property == null)
            throw new ArgumentException("Could not get property info for member " + memberExpression.Member.ToString());

        // This expression represents what the property will be set to.
        Expression paramSet;
        if (paramV.Type == property.PropertyType)
            paramSet = paramV;
        else
            paramSet = Expression.Convert(paramV, property.PropertyType);

        // Handle read-only properties (have no setter).
        if (!property.CanWrite)
        {
            setter = (t, v) =&gt; Debug.Write("Cannot set read-only property: " + property.ToString());
            return false;
        }

        // This expression represents calling the property setter.
        var call = Expression.Call(paramT, property.SetMethod, paramSet);

        // Compile the expressions into a lambda.
        setter = Expression.Lambda&lt;Action&lt;T, V&gt;&gt;(call, paramT, paramV).Compile();
    }
    else
    {
        // The member was not a field or a property.
        setter = (t, v) =&gt; Debug.Write("Setter invoked for invalid expression");
        return false;
    }
    return true;
}


Usage:

public class A
{
    public string Property { get; set;}
}

// Define the variables to hold the out parameters.
Func&lt;A, string&gt; getter;
Action&lt;A, string&gt; setter;

// Call function to use expression trees to create the getter and setter.
CreateGetterSetter&lt;A, string&gt;(a =&gt; a.Property, out getter, out setter);

// Now you can use "getter" to get A.Property...
var inst = new A { Property = "value" };
var value = getter(inst); // value = "value"

// ... and "setter" to set A.Property...
setter(inst, "new"); // inst.Property = "new"
value = getter(inst); // value = "new";


And to implement Round this way...

public static void Round&lt;T&gt;(IEnumerable&lt;T&gt; collection, params Expression&lt;Func&lt;T, decimal&gt;&gt;[] getterExpressions)
{
    // Create all the lambdas up-front. This is expensive, so you should cache this somewhere rather than 
    // re-compiling all the expressions every time.
    var gettersSetters = new Tuple&lt;Func&lt;T, decimal&gt;, Action&lt;T, decimal&gt;&gt;[getterExpressions.Length]; 
    for(int i=0;i&lt;getterExpressions.Length;i++)
    {
        Func&lt;T, decimal&gt; getter;
        Action&lt;T, decimal&gt; setter;
        CreateGetterSetter&lt;T, decimal&gt;(getterExpressions[i], out getter, out setter);
        gettersSetters[i] = Tuple.Create(getter, setter);
    }

    foreach (var item in collection)
    {
        foreach (var tuple in gettersSetters)
        {
            var getter = tuple.Item1;
            var setter = tuple.Item2;

            var value = getter(item);
            value = Math.Round(value, 1);
            setter(item, value);
        }
    }
}


Hope that helps!