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.