2013-05-03 1 views
1

나는 내 목록 컬렉션에 동적 프로젝트를 적용하려고합니다. 사용자는 주목할만한 항목이지만 내 목록의 속성을 선택할 것입니다. LINQ 문에서 열의 하위 집합을 가져 오려고합니다. Dynamic LINQ를 사용하고 싶습니다. any1은 표현식 트리로 프로젝트를 구현하는 방법을 제공 할 수 있습니다.LINQ를 통해 목록에 식 트리 적용

재산권 XXXX이 유형에 대해 정의되지 않은 경우, '나는 속성을 읽는 동안, 그것은 예외를 throw 작동하지 않는 경우,

내가 코드를 아래에 구현하려고 ... 푸른 테이블 저장 동적 투사을 적용 할 선택 System.String '

코드 : 당신은 당신이 모델의 클래스 정의를 게시하는 경우

DataMovementDataContext dbMovement = new DataMovementDataContext(); 
var entity = dbMovement.ListofAccountingDocs2_1075s.AsQueryable(); 
Type type = entity.ElementType; 
var entityParam = Expression.Parameter(entity.ElementType, "row"); 
Expression expr = entityParam; 
string[] props = "AccountingDocumentNbr,GLCompanyCode,DocumentFiscalYearNbr".Split(','); 
var epr = GenerateMemberExpression<ListofAccountingDocs2_1075, string>("Name"); 

foreach (string prop in props) 
{ 
    // use reflection (not ComponentModel) to mirror LINQ 
    PropertyInfo pi = type.GetProperty(prop); 
    expr = Expression.Property(expr, pi); 
    // type = pi.PropertyType; //Property 'System.String GLCompanyCode' is not defined for type 'System.String' 
} 

// row => row.Property 
// var columnLambda = Expression.Lambda( Expression.Property(entityParam, "GLCompanyCode"), entityParam); 
var columnLambda = Expression.Lambda(Expression.Property(expr, "AccountingDocumentNbr,GLCompanyCode"), entityParam); 

// Items.Select(row => row.Property) 
var selectCall = Expression.Call(typeof(Queryable), "Select", new Type[] { entity.ElementType, columnLambda.Body.Type }, entity.Expression, columnLambda); 

// Items.Select(row => row.Property).Distinct 
var distinctCall = Expression.Call(typeof(Queryable), "Distinct", new Type[] { typeof(string) }, selectCall); 

// colvalue => colvalue 
var sortParam = Expression.Parameter(typeof(string), "AccountingDocumentNbr"); 
var columnResultLambda = Expression.Lambda(sortParam, sortParam); 

// Items.Select(row => row.Property).Distinct.OrderBy(colvalue => colvalue) 
var ordercall = Expression.Call(typeof(Queryable), "OrderBy", 
      new Type[] { typeof(string), columnResultLambda.Body.Type }, 
      distinctCall, columnResultLambda); 

var result = entity.Provider.CreateQuery(ordercall); 
foreach (var item in result) 
{ 
    Console.Write(item); 
} 
+3

"작동하지 않습니다."에 대해 자세히 설명하십시오. –

+0

내 게시물을 편집했습니다. 투표 상태를 변경하십시오. – user145610

답변

3

그것은 방법이 쉬울 것 사용.

그러나 여러 속성을 연결하여 가져 오는 중입니다. 이것은 작동하지 않습니다. 나는 당신이 원하는 것은 생각 :

new { 
     AccountingDocumentNbr = document.AccountingDocumentNbr, 
     GLCompanyCode = document.GLCompanyCode , 
     DocumentFiscalYearNbr = document.DocumentFiscalYearNbr 
    }; 

하지만 foreach (string prop in props) 루프는 당신에게 제공하기 위해 필요한 것이 무엇 실제로 : 당신이 있기 때문에 document.AccountingDocumentNbr가하는 string처럼

document.AccountingDocumentNbr.GLCompanyCode.DocumentFiscalYearNbr 

지금, 그것은 본다 점점 Property 'System.String GLCompanyCode' is not defined for type 'System.String' 오류가 발생했습니다. 이와 같이 보면 오류가 발생합니다 ... System.StringGLCompanyCode 속성을 가지지 않으므로 연결된 속성식이 필요합니다. 그 밖의 다른 일이있을 수 있습니까?

이미 솔루션에 해당 유형의 인스턴스가없는 경우 타겟팅하는 것처럼 보이는 익명 개체를 가져올 수 없습니다. 익명 유형이 동적 유형이 아니기 때문입니다.. 모양이 비슷할 수도 있지만 실제로는 internal types compiled into the assembly이며 Equals(object obj), GetHashCode()ToString()에 대한 동일한 멤버 및 맞춤 우선 적용으로 다른 클래스와 다르게 작동하지 않습니다. 따라서 원하는 정의로 클래스를 참조 할 수있는 방법이 없으면 반사를 사용하여 이러한 멤버에 액세스 할 수 없습니다 (은 존재하지 않기 때문에). 람다 식을 사용하는 것이 훨씬 낫습니다.

좀 더 명확하게하기 위해, 위의 익명 유형에 대한 클래스 정의는 (거의) 다음과 같습니다.

public class <>f__AnonymousType0<T1,T2,T3> 
{ 
    private readonly T1 accountingDocumentNbr; 
    private readonly T2 glCompanyCode; 
    private readonly T3 documentFiscalYearNbr; 

    public T1 AccountingDocumentNbr 
    { 
     get { return accountingDocumentNbr; } 
    } 

    public T2 GLCompanyCode 
    { 
     get { return glCompanyCode; } 
    } 

    public T3 DocumentFiscalYearNbr 
    { 
     get { return documentFiscalYearNbr; } 
    } 

    public <>f__AnonymousType0(T1 accountingDocumentNbr, T2 glCompanyCode, T3 documentFiscalYearNbr) 
    { 
     this.accountingDocumentNbr = accountingDocumentNbr; 
     this.glCompanyCode = glCompanyCode; 
     this.documentFiscalYearNbr = documentFiscalYearNbr; 
    } 

    public override string ToString() 
    { 
     var builder = new StringBuilder(); 
     builder.Append("{ AccountingDocumentNbr = "); 
     builder.Append(AccountingDocumentNbr); 
     builder.Append(", GLCompanyCode = "); 
     builder.Append(GLCompanyCode); 
     builder.Append(", DocumentFiscalYearNbr = "); 
     builder.Append(DocumentFiscalYearNbr); 
     builder.Append(" }"); 
     return builder.ToString(); 
    } 

    public override bool Equals(object value) 
    { 
     var type = value as <>f__AnonymousType0<T1,T2,T3>; 
     return (type != null) && EqualityComparer<T1>.Default.Equals(type.AccountingDocumentNbr, AccountingDocumentNbr) && EqualityComparer<T2>.Default.Equals(type.GLCompanyCode, GLCompanyCode) && EqualityComparer<T3>.Default.Equals(type.DocumentFiscalYearNbr, DocumentFiscalYearNbr); 
    } 

    public override int GetHashCode() 
    { 
     int num = 0x7a2f0b42; 
     num = (-1521134295*num) + EqualityComparer<T1>.Default.GetHashCode(AccountingDocumentNbr); 
     num = (-1521134295*num) + EqualityComparer<T2>.Default.GetHashCode(GLCompanyCode); 
     return (-1521134295*num) + EqualityComparer<T3>.Default.GetHashCode(DocumentFiscalYearNbr); 
    } 
} 
0

내 문제를 해결할 수있었습니다.

public static Expression<Func<ListofAccountingDocs2_1075, ListofAccountingDocs2_1075>> BuildExpression(string parameters) 
{ 
    dynamic test = new ExpandoObject(); 
    var sourceMembers = typeof(ListofAccountingDocs2_1075).GetProperties(); 

    string[] selectparams = parameters.Split(',');//property names are comma seperated 

    foreach (var item in selectparams) 
     {   
      ((IDictionary<string, object>)test).Add(item,string.Empty); 
     } 
    IDictionary<string,object> test2 = new Dictionary<string,object>(); 

    List<PropertyInfo> destinationProperties = new List<PropertyInfo>(); 

    foreach (var item in ((IDictionary<string, object>)test)) 
    { 
     var selectedColumn = typeof(ListofAccountingDocs2_1075).GetProperties().FirstOrDefault(k => 
     k.Name.Equals(item.Key)); 

     if (selectedColumn != null) 
      destinationProperties.Add(selectedColumn); 
    } 

    var name = "src"; 

    var parameterExpression = Expression.Parameter(typeof(ListofAccountingDocs2_1075), name); 

    return Expression.Lambda<Func<ListofAccountingDocs2_1075, ListofAccountingDocs2_1075>>(
     Expression.MemberInit(
      Expression.New(typeof(ListofAccountingDocs2_1075)), 
      destinationProperties.Select(k => Expression.Bind(k, 
       Expression.Property(
        parameterExpression, k.Name) 
       ) 
      ).ToArray() 
      ), 
     parameterExpression 
    ); 

}