通过引用 lambda 表达式为 属性 赋值
Assigning a value to a property by reference to a lambda expression
我有 2 个对象(一个 DTO 和一个入口框架对象),如果 DTO 中的相应值不同,我想更新 EF 实体。我设想它会这样做:
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?
}
}
}
我相信以下应该有效,但我不知道如何将值分配回 efObject。有人可以给我线索吗?
你可以这样做:
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;}
}
这是 DotNetFiddle 上的工作示例 - https://dotnetfiddle.net/k1qLZH
此示例仅供 属性 和成员访问。因此,如果您的表达式将具有另一个签名,例如 method,sub 属性,字段访问,则此代码将失败。
另一种不需要 lambda 编译但需要一些时间的方法可能是:
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);
}
我有 2 个对象(一个 DTO 和一个入口框架对象),如果 DTO 中的相应值不同,我想更新 EF 实体。我设想它会这样做:
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?
}
}
}
我相信以下应该有效,但我不知道如何将值分配回 efObject。有人可以给我线索吗?
你可以这样做:
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;}
}
这是 DotNetFiddle 上的工作示例 - https://dotnetfiddle.net/k1qLZH
此示例仅供 属性 和成员访问。因此,如果您的表达式将具有另一个签名,例如 method,sub 属性,字段访问,则此代码将失败。
另一种不需要 lambda 编译但需要一些时间的方法可能是:
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);
}