2013-05-03 44 views
1

我想爲我的列表集合應用動態項目。用戶將選擇正在註釋的列,但是我的列表的屬性。我想從LINQ語句中獲得列的子集。我想使用動態LINQ。任何1都可以提供如何使用表達式樹來實現項目。我想申請在Azure表存儲動態投影..通過LINQ應用表達式列表

我嘗試執行下面的代碼,它不工作,它拋出異常,而讀取屬性:

物業XXXX沒有爲類型定義' 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

請詳細說明「它不工作」。 – 2013-05-03 20:36:49

+0

我已編輯我的帖子。請更改投票狀態 – user145610 2013-05-03 21:21:51

回答

3

如果您發佈的類定義,你是模特這將是比較容易的方式使用。

但是,它看起來像你正試圖通過鏈接他們得到多個屬性。這不起作用。我想你想要的是:

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

foreach (string prop in props)循環實際上是你需要爲了能給你帶來什麼:

document.AccountingDocumentNbr.GLCompanyCode.DocumentFiscalYearNbr 

現在,它看起來像document.AccountingDocumentNbrstring,因爲你是得到那個Property 'System.String GLCompanyCode' is not defined for type 'System.String'錯誤。當你看到像這樣的錯誤是有道理... System.String沒有GLCompanyCode屬性,你正在構建期望它有一個鏈接的屬性表達式。還會發生什麼?

你不會是能夠得到匿名對象,它看起來像你的目標,除非有該類型的實例已經在您的解決方案。這是因爲匿名類型不是動態類型。他們可能看起來像,但它們實際上是internal types compiled into the assembly,他們不比用相同的部件和定製覆蓋任何其他類的函數有什麼不同的Equals(object obj)GetHashCode()ToString()。所以,除非你有辦法引用與您正在查找的定義一個類時,你不會是能夠訪問使用反射(因爲它們不存在)這些成員。只使用lambda表達式會更好。

對於一個小更加清楚,下面是上述匿名類型的類定義是什麼樣子(差不多)。

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 
    ); 

}