2016-07-21 11 views
0

Ich habe eine Klasse namens DataResponse erstellt, die mehr als 40 öffentliche Felder enthält. Die Klasse DataResponse hat die gleiche Anzahl von Feldern und Typ wie in meiner Datenbank DataRepoes (nehmen wir an).C# Wie kann ich eine Sammlung von benutzerdefinierten Objekten erstellen, ohne jedes Feld zu durchlaufen?

Gibt es eine Möglichkeit überhaupt etwas wie linq unten zu tun, wo ich eine Liste von Objekten erstellen und automatisch die Felder DataResponse von dem, was in der DB ist, zugeordnet sind? Ansonsten muss ich jedes einzelne dieser 40 Felder buchstabieren und manuell zuweisen, wenn ich die DataResponse-Klasse neu starte. Danke

List<Classes.DataResponse> res = (from rx in con.DataRepoes 
    where iaccess.Contains(rx.STOREID) 
    select new Classes.DataResponse).ToList<Classes.DataResponse>(); 
+2

Vielleicht [AutoMapper] (http://automapper.org/)? –

Antwort

1

Wenn Sie nicht über die Flexibilität von AutoMapper bereitgestellt müssen oder wollen nicht eine dritte Partei Bibliothek verwenden, können Sie die folgende vereinfachte benutzerdefinierte Erweiterung-Methode verwenden:

public static class QueryableExtensions 
{ 
    public static IQueryable<TResult> SelectTo<TResult>(this IQueryable source) 
    { 
     var sourceType = source.ElementType; 
     var resultType = typeof(TResult); 
     var parameter = Expression.Parameter(sourceType, "x"); 
     var bindings = 
      from rm in resultType.GetProperties().Concat<MemberInfo>(resultType.GetFields()) 
      join sm in sourceType.GetProperties().Concat<MemberInfo>(sourceType.GetFields()) 
       on rm.Name equals sm.Name 
      select Expression.Bind(rm, Expression.MakeMemberAccess(parameter, sm)); 
     var body = Expression.MemberInit(Expression.New(resultType), bindings); 
     return source.Provider.CreateQuery<TResult>(Expression.Call(
      typeof(Queryable), "Select", new[] { sourceType, resultType }, 
      source.Expression, Expression.Quote(Expression.Lambda(body, parameter)))); 
    } 
} 

Es wird versuchen, alle wählen die Eigenschaften/Felder, die nach Namen übereinstimmen. Scheitert, wenn übereinstimmende Eigenschaften/Feldtypen sich unterscheiden.

Verwendungsbeispiel:

Methode Syntax

var res = con.DataRepoes 
    .Where(rx => iaccess.Contains(rx.STOREID)) 
    .SelectTo<Classes.DataResponse>() 
    .ToList(); 

Abfragesyntax

var res = 
    (from rx in con.DataRepoes 
    where iaccess.Contains(rx.STOREID) 
    select rx) 
    .SelectTo<Classes.DataResponse>() 
    .ToList(); 
+0

danke. Ja, ich bevorzuge keine Drittanbieter-Bibliothek, da diese die Sicherheitsüberprüfung durchlaufen muss. Ich werde es versuchen. – Zuzlx

+0

Danke Ivan. Arbeitete wie ein Wiegenlied zu einem weinenden Baby. Es wäre toll für den nächsten Narren (wie mich), wenn du deinen Code durchgehen und uns zeigen kannst, wie man fischt. Ich verstehe es den ganzen Weg bis 'on rm.Name gleich sm.Name' Zeile. – Zuzlx

+0

Lol, es ist eine LINQ-Methode, Quelleigenschaft/Feld der Zieleigenschaft/dem Zielfeld nach Namen zuzuordnen - siehe [Join] (https://msdn.microsoft.com/en-us/library/bb311040.aspx). Froh, dass geholfen hat, Happy Coding :) –

2

Sie können Automapper Queryable Extensions dafür verwenden.

Unter der Annahme, die Felder in Classes.DataResponse haben die gleichen Namen wie die, die in DataRepoes Sie können dann tun:

// During your application bootstrap, configure AutoMapper to create a map between the two types 
Mapper.Initialize(cfg => cfg.CreateMap<DataRepoes, Classes.DataResponse); 


// Then you can ask AutoMapper to project the IQueryable directly to your DTO 
List<Classes.DataResponse> res = con.DataRepoes 
            .Where(rx => iaccess.Contains(rx.STOREID)) 
            .ProjectTo<Classes.DataResponse>() 
            .ToList();          
1

dies nicht möglich ist, mithilfe von LINQ. Sie können jedoch "AutoMapper" verwenden, um dies zu erreichen. Nur CreateMap für diese beiden Klassen und dann auf Karte sie

Mapper.CreateMap<DataResponse,DataRepo>();//Assuming DataRepoes is collection of DataRepo types 
List<Classes.DataResponse> res = (from rx in con.DataRepoes 
            where iaccess.Contains(rx.STOREID) 
            select Mapper.Map<Classes.DataResponse>(rx)). 
            ToList<Classes.DataResponse>(); 

Hoffnung, die hilft !!