简体   繁体   中英

map common properties in separate method using generics

I have a class MechanicalData and in that i have list of objects and in the below function i am trying to form list of objects with values coming from input.

Mechanicaldata class looks like below

public class MechanicalData
{
    public List<LibraryA170> AirflowsA170 { get; set; }
    ......
}

and the classes libraryA170 and LibraryAcoustic looks like as follows

public class LibraryA170 : AEIMasterBase
{
    public string Category { get; set; }
    public string SpaceFunction { get; set; }
    [Column(TypeName = "varchar(32)")]
    public DirectExhaust? DirectExhaust { get; set; }
    .....
    ......
}

public class LibraryAcoustic : AEIMasterBase
{
    public string Category { get; set; }
    public string SpaceFunction { get; set; }
    public double? NoiseCriteria { get; set; }
    .......
}

and base class AEIMasterBase looks like as below

public class AEIMasterBase
{
    public Guid Id { get; set; }
    public MasterSection MasterSection { get; set; }
    public List<string> NotesHTML { get; set; }
    public bool? IsApproved { get; set; }
    public Guid? InitialRevisionId { get; set; }
    public Guid? LatestRevisionId { get; set; }
    public int? Revision { get; set; }
 }

Below i am trying to map all those fields with LINQ select

    private static MechanicalData TransformedMechanicalData(MechanicalData sourceMechanicalData, Dictionary<string, MasterSection> masterSectionMappedLibrary)
    {         
        return new MechanicalData
        {
            AirflowsA170 = sourceMechanicalData.AirflowsA170.Select(airflow170 => new LibraryA170
            {
                Id = airflow170.Id, 
                InitialRevisionId = airflow170.InitialRevisionId,
                LatestRevisionId = airflow170.LatestRevisionId,
                IsApproved = true,
                Revision = airflow170.Revision,
                NotesHTML = airflow170.NotesHTML,
                SpaceFunction = airflow170.SpaceFunction,
                Category = airflow170.Category,
                MasterSection = masterSectionMappedLibrary["Library A170"],
                ........
            }).ToList(),

            Acoustic = sourceMechanicalData.Acoustic.Select(acoustic => new LibraryAcoustic
            {
                Id = acoustic.Id,
                InitialRevisionId = acoustic.InitialRevisionId,
                LatestRevisionId = acoustic.LatestRevisionId,
                IsApproved = true,
                Revision = acoustic.Revision,
                NotesHTML = acoustic.NotesHTML,
                Category = acoustic.Category,
                SpaceFunction = acoustic.SpaceFunction,
                ......
            }).ToList()
        };
    }

is there any way i can pass two objects to a method and map common properties inside that method and leave uncommon properties to be mapped inside the select statement while adding to the list. I am looking for something like as below if possible

public static class ItemExtensionMethods
{
    public static readonly Expression<Func<Item, MinimalItem>> MapToMinimalItemExpr = 
        source => new MinimalItem 
        {
            Id = source.Id,  // only common properties like id, revision, IsApproved 
            Property1 = source.Property1
        };
}

below are some common properties

  Id = airflow170.Id, 
  InitialRevisionId = airflow170.InitialRevisionId,
  LatestRevisionId = airflow170.LatestRevisionId,
  .......

Could any one please suggest any idea on this, Many thanks in advance

update getting below error

在此处输入图像描述

Given two expression tree's, you want to locate the two MemberInitExpression nodes, merge their MemberBinding 's and swap any ParameterExpression .

class LocateBindings : ExpressionVisitor
{
    public IEnumerable<MemberBinding> Bindings { get; private set; }
    protected override Expression VisitMemberInit(MemberInitExpression node)
    {
        Bindings = node.Bindings;
        return base.VisitMemberInit(node);
    }
}

class MergeBindings : ExpressionVisitor
{
    private IEnumerable<MemberBinding> bindings;
    private ParameterExpression parameter;
    public MergeBindings(IEnumerable<MemberBinding> bindings, ParameterExpression parameter)
    {
        this.bindings = bindings;
        this.parameter = parameter;
    }
    protected override Expression VisitMemberInit(MemberInitExpression node)
        => node.Update(node.NewExpression, 
            node.Bindings.Concat(bindings)
                .Select(VisitMemberBinding));
    protected override Expression VisitParameter(ParameterExpression node)
        => parameter;
}

public static Expression<Func<P, D>> Merge<BP, P, B, D>(
    Expression<Func<BP, B>> baseExpr,
    Expression<Func<P, D>> derivedExpr
)
    where D:B where P:BP
{
    var locate = new LocateBindings();
    locate.Visit(baseExpr);

    var merge = new MergeBindings(locate.Bindings, derivedExpr.Parameters[0]);
    return merge.VisitAndConvert(derivedExpr, "");
}

For example;

Expression<Func<[insert type], AEIMasterBase>> baseExpression = basearg => new AEIMasterBase
{
    Id = basearg.Id, 
    InitialRevisionId = basearg.InitialRevisionId,
    LatestRevisionId = basearg.LatestRevisionId,
    IsApproved = true,
    Revision = basearg.Revision,
    NotesHTML = basearg.NotesHTML,
    SpaceFunction = basearg.SpaceFunction,
};
Expression<Func<[insert type], LibraryA170>> derivedExpression = airflow170 => new LibraryA170
{
    Category = airflow170.Category,
    MasterSection = masterSectionMappedLibrary["Library A170"],
};
var merged = Merge(baseExpression, derivedExpression);

...
AirflowsA170 = sourceMechanicalData.AirflowsA170.Select(merged).ToList()
...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM