[英]set nested properties of object while mapping
我正在使用表達式樹作為自動映射器的替代方法,將 map 源屬性用於使用以下代碼的目標屬性
What i am doing is, I have created static method inside static class for mapping and assigning inner child object property to outer object property
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 targetProperties= typeof(TDest).GetProperties().Where(p => p.CanWrite);
var propertyMap =
from d in targetProperties
join s in sourceProperties on new { d.Name, d.PropertyType } equals new { s.Name, s.PropertyType }
where d.Name != "SourceOfDataId" && d.Name!= "SourceOfData"
select new { Source = s, Dest = d };
var itemParam = Expression.Parameter(typeof(TSource), "item");
var memberBindings = propertyMap.Select(p => (MemberBinding)Expression.Bind(p.Dest, Expression.Property(itemParam, p.Source))).ToList();
var sourceOfDataIdProp = targetProperties.FirstOrDefault(s => s.Name == "SourceOfDataId");
if (sourceOfDataIdProp != null)
{
memberBindings.Add(Expression.Bind(sourceOfDataIdProp,Expression.Convert(Expression.Property(Expression.Property(itemParam, "SourceOfData"),"Id"),typeof(Guid?))));
}
var sourceOfDataProp = targetProperties.FirstOrDefault(s => s.Name == "SourceOfData");
if(sourceOfDataProp != null)
{
// here i would like to update `sourceOfData` object property "isApproved"
}
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;
}
}
我在下面使用上述方法將 map 源屬性轉換為目標屬性
AirflowsLab = sourceMechanicalData.AirflowsLab.Select(a => PropertyMapper<LibraryLabAirflow, LibraryLabAirflow>.Mapper(a, masterSectionMappedLibrary)).ToList();
LibraryLabAirflow 的結構如下所示
public class LibraryLabAirflow
{
[ForeignKey("SourceOfData")]
public Guid? SourceOfDataId { get; set; }
public virtual CodeStandardGuideline SourceOfData { get; set; }
}
Above mapping is working fine, what i am trying is now that i need to access the sourceOfData
child object of target and update the property for sourceOfData
and map that updated child object to source child object sourceOfData
.
下面是sourceOfData object詳細信息
"SourceOfData":{
"Id": "c5bf3585-50b1-4894-8fad-0ac884343935",
"IsApproved": null, // trying to set this to true instead of null inside target object
"MasterSection": null
},
在這種情況下,我不確定如何使用表達式樹訪問子 object 屬性,並且我無法使用 automapper 庫。 任何人都可以讓我知道如何訪問子 object 屬性並更新並分配回目標。
我試圖生成的表達式看起來像這個source.SourceOfData = target.SourceOfData
但在此之前我需要更新target.SourceOfData
的屬性之一
提前謝謝了
所需的表達:
AirflowsLab = sourceMechanicalData.AirflowsLab.Where(a => a != null).Select(item => new LibraryLabAirflow()
{
SourceOfData = new CodeStandardGuideline()
{
IsApproved = true,// trying to set this through expression tree
City = item.SourceOfData.City
......
.......
}
}).ToList(),
像這樣嘗試也不行,1
var sourceOfDataProp = targetProperties.FirstOrDefault(s => s.Name == "SourceOfData");
if(sourceOfDataProp != null)
{
// here need to get the sourceofdata properties
var sourceOfDataProperty = Expression.Property(Expression.Constant(sourceOfDataProp), "IsApproved");
}
更新:
如果sourceOfDataProp != null
塊,我已經實現了內部邏輯,但出現錯誤
if (sourceOfDataProp != null)
{
var targetitemParam = Expression.Parameter(typeof(TTarget), "item");
var sourceOfDataPropertiesFilter = new List<string>()
{
"IsApproved"
};
var sourceItem = Expression.Property(itemParam, typeof(TSource).GetProperty("SourceOfData"));
var sourcePropertyInfo = sourceItem.Type.GetProperties().Where(p => p.CanRead);
var targetItem = Expression.Property(targetitemParam, typeof(TTarget).GetProperty("SourceOfData"));
var targetPropertyInfo = targetItem.Type.GetProperties().Where(p => p.CanWrite);
var sourceOfDataPropertyMap = from tp in targetPropertyInfo
join sp in sourcePropertyInfo
on new { tp.Name, tp.PropertyType } equals new { sp.Name, sp.PropertyType }
where !sourceOfDataPropertiesFilter.Contains(tp.Name)
select new { Source = sp, Target = tp };
// getting error at below line type of arguments does not match
var sourceOfDataMemberBindings = sourceOfDataPropertyMap.Select(p => Expression.Bind(p.Target, Expression.PropertyOrField(targetitemParam, "SourceOfData"))).ToList();
}
我已經解決了這個問題,如下所示
if (sourceOfDataProp != null)
{
var targetItemParam = Expression.Parameter(typeof(TTarget), "item");
var sourceOfDataPropertiesFilter = new List<string>()
{
"IsApproved"
};
var sourceItem = Expression.Property(itemParam, typeof(TSource).GetProperty("SourceOfData"));
var sourceOfDataSourceProperties = sourceItem.Type.GetProperties().Where(p => p.CanRead);
var targetItem = Expression.Property(targetItemParam, typeof(TTarget).GetProperty("SourceOfData"));
var sourceOfDataTargetProperties = targetItem.Type.GetProperties().Where(p => p.CanWrite);
var sourceOfDataPropertyMap = sourceOfDataTargetProperties.Join(sourceOfDataSourceProperties,
t => new { t.Name, t.PropertyType },
s => new { s.Name, s.PropertyType },
(t, s) => new { Source = s, Target = t })
.Where(t => !sourceOfDataPropertiesFilter.Contains(t.Target.Name));
var sourceOfDataMemberBindings = sourceOfDataPropertyMap.Select(p => Expression.Bind(p.Target, Expression.Property(sourceItem, p.Source))).ToList();
var sourceOfDataIsApprovedProp = sourceOfDataTargetProperties.FirstOrDefault(s => s.Name == "IsApproved");
if (sourceOfDataIsApprovedProp != null)
{
sourceOfDataMemberBindings.Add(Expression.Bind(sourceOfDataIsApprovedProp, Expression.Constant(true, typeof(bool?))));
}
var sourceOfDataExpression = Expression.New(typeof(DesignHub.Entities.CodeStandardGuideline));
var sourceOfDataMemberInitExpression = Expression.MemberInit(sourceOfDataExpression, sourceOfDataMemberBindings);
memberBindings.Add(Expression.Bind(sourceOfDataProp, sourceOfDataMemberInitExpression));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.