簡體   English   中英

在映射時設置 object 的嵌套屬性

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM