【发布时间】:2021-07-08 23:12:18
【问题描述】:
大家好,我正在使用表达式树通过使用以下代码创建表达式来将值从源映射到目标
public static class PropertyMapper<TSource, TDest>
{
private static Expression<Func<TSource, Dictionary<string, MasterSection>, TDest>> _mappingExpression;
private static Func<TSource, Dictionary<string, MasterSection>, TDest> _mapper;
static PropertyMapper()
{
_mappingExpression = ProjectionMap();
_mapper = _mappingExpression.Compile();
}
public static Func<TSource, Dictionary<string, MasterSection>, TDest> Mapper => _mapper;
public static Expression<Func<TSource, Dictionary<string, MasterSection>, TDest>> ProjectionMap()
{
var sourceProperties = typeof(TSource).GetProperties().Where(p => p.CanRead);
var destProperties = typeof(TDest).GetProperties().Where(p => p.CanWrite);
var propertyMap =
from d in destProperties
join s in sourceProperties on new { d.Name, d.PropertyType } equals new { s.Name, s.PropertyType }
where d.Name != "SourceOfDataId"
select new { Source = s, Dest = d };
var itemParam = Expression.Parameter(typeof(TSource), "item");
var dictParam = Expression.Parameter(typeof(Dictionary<string, MasterSection>), "dict");
var memberBindings = propertyMap.Select(p => (MemberBinding)Expression.Bind(p.Dest, Expression.Property(itemParam, p.Source))).ToList();
var sourceOfDataProp = destProperties.FirstOrDefault(s => s.Name == "SourceOfDataId");
if (sourceOfDataProp != null)
{
// here i am setting one of the inner object(SourceOfData) ID to outer object nullable guid property (SourceOfDataId)
memberBindings.Add(Expression.Bind(sourceOfDataProp, Expression.Property(Expression.Property(itemParam, "SourceOfData"), "Id")));
}
var newExpression = Expression.New(typeof(TDest));
var memberInitExpression = Expression.MemberInit(newExpression, memberBindings);
var projection = Expression.Lambda<Func<TSource, Dictionary<string, MasterSection>, TDest>>(memberInitExpression, itemParam, dictParam);
return projection;
}
}
然后像下面这样调用上面的方法
AirflowsLab = sourceMechanicalData
.AirflowsLab
.Select(a => PropertyMapper<LibraryLabAirflow, LibraryLabAirflow>
.Mapper(a, masterSectionMappedLibrary)).ToList()
我在源实体和目标实体上有这些属性 SourceOfDataId、IsApproved,我试图将 IsApproved 设置为 true,并将 sourceOfDataId 设置为相应的值。
此项目映射错误值设置为 SourceOfDataId 而不是内部对象属性 Id 后
实体 LibraryLabAirflow 是这样的
public class LibraryLabAirflow
{
[ForeignKey("SourceOfData")]
public Guid? SourceOfDataId { get; set; }
public virtual CodeStandardGuideline SourceOfData { get; set; }
public bool? IsApproved { get; set; }
}
我也尝试过下面的表达式绑定,但都没有成功
尝试 1:
var sourceOfDataPropertyBind = Expression.Bind(sourceOfDataProp, Expression.Property(Expression.Property(itemParam, "SourceOfData"),typeof(Guid?), "Id"));
尝试 2:
var sourceOfDataPropertyBind = Expression.Bind(sourceOfDataProp, Expression.Property(Expression.Property(itemParam, typeof(Guid?), "SourceOfData"), "Id"));
并试图摆脱上面的这些表达式
airflowLab => new LibraryLabAirflow
{
IsApproved = true,
SourceOfData = airflowLab.SourceOfData,
SourceOfDataId = airflowLab.SourceOfData.Id,
}
谁能告诉我上面的代码哪里做错了,提前谢谢。
【问题讨论】:
-
谁能告诉我为什么我不能设置属性值
标签: c# .net-core entity-framework-core linq-to-entities expression-trees