I have 2 objects (a DTO and a Entry Framework Object) and I want to update the EF Entity if the corresponding value in the DTO is different. I envisage it would be done like this:
UpdateIfDifferent(dtoObject, x => x.MailStatus, efObject, r => r.MailStatus);
UpdateIfDifferent(dtoObject, x => x.WebStatus, efObject, r => r.WebStatus);
private void UpdateIfDifferent<TOriginal, TOriginalProperty, TUpdated, TUpdatedProperty>
(TOriginal original, Expression<Func<TOriginal, TOriginalProperty>> originalProperty,
TUpdated updated, Expression<Func<TUpdated, TUpdatedProperty>> updatedProperty)
{
if (!originalProperty.Compile()(original).Equals(updatedProperty.Compile()(updated))) {
// how do I assign back to original from updated?
}
}
}
I believe the following should work but I do not know how I can assign the value back to the efObject. Can anybody clue me in please?
You can do like this:
public static void Main()
{
var original = new TestEntity();
original.Name = "test";
var dto = new TestDTO();
dto.FirstName = "New Value";
UpdateIfDifferent(original, o => o.Name, dto, d => d.FirstName);
Console.WriteLine(original.Name);
}
private static void UpdateIfDifferent<TOriginal, TOriginalProperty, TUpdated, TUpdatedProperty>
(TOriginal original, Expression<Func<TOriginal, TOriginalProperty>> originalProperty,
TUpdated updated, Expression<Func<TUpdated, TUpdatedProperty>> updatedProperty)
{
if (!originalProperty.Compile()(original).Equals(updatedProperty.Compile()(updated)))
{
var updatedMember = (updatedProperty.Body as MemberExpression).Member as PropertyInfo;
var updatedValue = updatedMember.GetValue(updated);
var member = (originalProperty.Body as MemberExpression).Member as PropertyInfo;
member.SetValue(original, updatedValue);
}
}
public class TestEntity
{
public string Name {get;set;}
}
public class TestDTO
{
public string FirstName {get;set;}
}
Here is a working sample on DotNetFiddle - https://dotnetfiddle.net/k1qLZH
This sample is just for property and member access. So if your expression will have another signature like method,sub property, field access then this code will fail.
Another approach without lambda compilation that takes some time might be:
private static void UpdateIfDifferent<TOriginal, TOriginalProperty, TUpdated, TUpdatedProperty>
(TOriginal original, Expression<Func<TOriginal, TOriginalProperty>> originalProperty,
TUpdated updated, Expression<Func<TUpdated, TUpdatedProperty>> updatedProperty)
{
var updatedMember = (updatedProperty.Body as MemberExpression).Member as PropertyInfo;
var updatedValue = updatedMember.GetValue(updated);
var originalMember = (originalProperty.Body as MemberExpression).Member as PropertyInfo;
var originalValue = originalMember.GetValue(original);
if (!object.Equals(updatedValue, originalValue))
originalMember.SetValue(original, updatedValue);
}