简体   繁体   中英

C# how to set parameter value by Func Delegate

I need a clean way to update an object using parameters of same class. I am defining list of fields as Func<T, object> delegates. These are lists that should be compared and updated if nessecary. Unfortunately I can't figure out a clean way to implement it.

Following code doesn't work:

public class UpdatableClass
{
    public int Id { get; set; }
    public int IntValue { get; set; }
    public string StringValue { get; set; }
    public DateTime ModifiedDate { get; set; }


    private List<Func<UpdatableClass, object>> UpdatableFields =
        new List<Func<UpdatableClass, object>>()
        {
            c => c.IntValue,
            c => c.StringValue
        };

    public bool Update(UpdatableClass newValues)
    {
        bool isUpdated = false;
        foreach (var fieldSelector in UpdatableFields)
        {
            object oldValue = fieldSelector(this);
            object newValue = fieldSelector(newValues);
            if (!newValue.Equals(oldValue))
            {
                oldValue = newValue;
                isUpdated = true;
            }
        }

        return isUpdated;
    }
}

[TestFixture]
public class UpdatableClassTests
{
    [Test]
    public void TestUpdateMethod()
    {
        UpdatableClass oldObject = new UpdatableClass()
        {
            StringValue = "OldString",
            IntValue = 3,
        };

        bool isUpdated = oldObject.Update(new UpdatableClass() { StringValue = "NewString", IntValue = 4 });

        Assert.IsTrue(isUpdated);
        Assert.AreEqual("NewString", oldObject.StringValue);
        Assert.AreEqual(4, oldObject.IntValue);
    }
}

This code can be used as possible solution for the problem. Instead of get only Func<T, object> you can use a tuple for both getter and setter (Func<UpdatableClass, object> Get, Action<UpdatableClass, object> Set) . I don't think that it's the best solution, but it resolves question and make test passing

public class UpdatableClass
{
    public int Id { get; set; }
    public int IntValue { get; set; }
    public string StringValue { get; set; }
    public DateTime ModifiedDate { get; set; }

    private List<(Func<UpdatableClass, object> Get, Action<UpdatableClass, object> Set)> UpdatableFields =
        new List<(Func<UpdatableClass, object>, Action<UpdatableClass, object>)>
        {
            (c => c.IntValue, (c, v) => { c.IntValue = Convert.ToInt32(v); }),
            (c => c.StringValue, (c, v) => { c.StringValue = v.ToString(); })
        };

    public bool Update(UpdatableClass newValues)
    {
        bool isUpdated = false;
        foreach (var field in UpdatableFields)
        {
            object oldValue = field.Get(this);
            object newValue = field.Get(newValues);
            if (!newValue.Equals(oldValue))
            {
                field.Set(this, newValue);
                isUpdated = true;
            }
        }

        return isUpdated;
    }
}   

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM