2009-09-23 16 views
19

Dört sütunlu bir DataTable var mı, Şirket (string), Fon (string)), Devlet (string), Değeri) (çift:System.LINQ.Dynamic: Bir liste içine (<T> (veya <T> numaralı başka herhangi bir koleksiyon)

Ben o sırada grubum seçer ya Şirketi, Fona veya Devletin, üzerinde gruplar ve dinamik bir sorgu oluşturmak için System.LINQ.Dynamic kullanmak istiyorum
table1.Rows.Add("Company 1","Fund 1","NY",100)); 
    table1.Rows.Add("Company 2","Fund 1","CA",200)); 
    table1.Rows.Add("Company 3","Fund 1","FL",300)); 
    table1.Rows.Add("Company 4","Fund 2","CA",400)); 
    table1.Rows.Add("Company 5","Fund 1","NY",500)); 
    table1.Rows.Add("Company 6","Fund 2","CA",600)); 
    table1.Rows.Add("Company 7","Fund 3","FL",700)); 

yukarıdaki sorgu

string groupbyvalue="Fund"; 
var q1= table1.AsEnumerable().AsQueryable() 
       .GroupBy(groupbyvalue,"it") 
       .Select("new ("+groupbyvalue+" as Group, Sum(Value) as TotalValue)"); 

seçilen groupbyvalue (Grup w): ilk sütun, ve toplam (değer) olarak kriterler Hasta her zaman bir dize olur ve toplamı her zaman bir çift olur, bu yüzden bir Sonuç Listesi gibi bir şeye dönüştürmek istiyorum. Sonuç, Properties Group (string) ve TotalValue (double) özelliklerine sahip bir nesnedir.

Bu konuda çok sıkıntı yaşıyorum, kimse biraz ışık tutabilir mi?

cevap

40

Öncelikle, Seç fıkrada Key gibi güncel gruplandırılmış değerini erişirsiniz: sorgu çalışması gerektiğini

.Select("new (Key as Group, Sum(Value) as TotalValue)"); 

. Daha zor olan soru, DynamicClass'dan devralınan dinamik olarak oluşturulmuş bir türe sahip olan döndürülen nesnelerin statik bir türe dönüştürülmesidir.

Seçenek 1: Dinamik nesnenin Group ve TotalValue özelliklerine erişmek için yansımayı kullanın.

Seçenek 2: Group ve TotalValue özelliklerine erişmek için, hafif kod üretimi için derlenmiş ifade ağaçlarını kullanın.

Seçenek 3: Güçlü yazılan bir sonucu desteklemek için Dinamik kütüphaneyi değiştirin.

ExpressionParser.Parse() yılında
  1. , özel alanda tür bağımsız değişkeni yakalamak: Bu oldukça basit olarak çıkıyor

    private Type newResultType; 
    public Expression Parse(Type resultType) 
    { 
        newResultType = resultType; 
        int exprPos = token.pos; 
        // ... 
    
  2. ExpressionParser.ParseNew() sonuna doğru, biz varsaymak önce newResultType kullanmaya çalışacağım dinamik bir türe: Nihayet

    Expression ParseNew() 
    { 
        // ... 
        NextToken(); 
        Type type = newResultType ?? DynamicExpression.CreateClass(properties); 
        MemberBinding[] bindings = new MemberBinding[properties.Count]; 
        for (int i = 0; i < bindings.Length; i++) 
         bindings[i] = Expression.Bind(type.GetProperty(properties[i].Name), expressions[i]); 
        return Expression.MemberInit(Expression.New(type), bindings); 
    } 
    
  3. biz Select() bir türü kesin sürümü gerekir: Orijinal Select() den

    public static IQueryable<TResult> Select<TResult>(this IQueryable source, string selector, params object[] values) 
    { 
        if (source == null) throw new ArgumentNullException("source"); 
        if (selector == null) throw new ArgumentNullException("selector"); 
        LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, typeof(TResult), selector, values); 
        return source.Provider.CreateQuery<TResult>(
         Expression.Call(
          typeof(Queryable), "Select", 
          new Type[] { source.ElementType, typeof(TResult) }, 
          source.Expression, Expression.Quote(lambda))); 
    } 
    

    yalnızca değişiklikler biz TResult referans yerlerdir.

Şimdi sadece dönmek için adlandırılmış türü gerekir:

public class Result 
    { 
     public string Group { get; set; } 
     public double TotalValue { get; set; } 
    } 

Ve güncellenmiş sorgu aşağıdaki gibi görünecektir:

IQueryable<Result> res = table1.AsQueryable() 
     .GroupBy(groupbyvalue, "it") 
     .Select<Result>("new (Key as Group, Sum(Value) as TotalValue)"); 
1

başka olasılık ile DLINQ sorgu dilini uzatmaktır sorgu dizesindeki new yan tümcesindeki tür adını belirleme olasılığı.

Değişiklikleri Dynamic.cs numaralı telefondan başka bir stackoverflow answer numaralı telefondan tanımladım.

Size aşağıdaki gibi sorguları poz izin verir:

1 jenerik desteklemek için dinamik linq Select yönteminin uzatın: Aşağıdaki arada <IExampleInterface> Listeye

IQueryable<Result> res 
    = table1.AsQueryable() 
    .GroupBy(groupbyvalue, "it") 
    .Select("new Result(Key as Group, Sum(Value) as TotalValue)") 
    as IQueryable<Result>; 
3

Döndüm dökme verilerle türleri. here

2 kullanımı (dahlbyk cevabı ilk satırına çok benzer) Select yöntemi ilk cevabı bakın

Select<dynamic>("new (Key as Group, Sum(Value) as TotalValue)") 

Birden sütunları gerekiyorsa, aşağıdakileri kullanabilirsiniz:

GroupBy(@"new (Fund, Column1, Column2)", "it"). 
Select<dynamic>("new (Key.Fund, Key.Column1, Key.Column2, Sum(Value) as TotalValue)") 

3 dönüştürün listelenecek veriler. Listesini dönüştürmek

var data = ... 
    GroupBy("...").Select<dynamic>("..."). 
    Cast<dynamic>().AsEnumerable().ToList(); 

4 Kullanım Impromptu <IExampleInterface>

var result = new List<IExampleInterface>(); 

foreach (var d in data) 
{ 
    dynamic r = Impromptu.ActLike<IExampleInterface>(d); 
    result.Add(r); 
} 
Listeye
İlgili konular