2012-12-02 24 views
5

de bilinmiyorsa IEnumerable IEnumerable Cast aşağıdaki imzası ile bir sıralama uzantısı yöntemi vardır: T derleme zamanında

public static IEnumerable<T> CustomSort<T>(this IEnumerable<T> source, string sortProperties) 

Biz bir süre önce yazmış ve onun şey yapıyor. Şimdi özel bir denetim oluşturuyorum ve DataSource özelliği IEnumerable (non-generic). Nesnelerin türünü jenerik olmayan bir IEnumerable içinde almanın bir yolu var mı?

"Özel bir denetim veri kaynağını sırala" sorunu milyonlarca kez çözüldü, ancak bir çözüm bulamıyorum.

cevap

1

Sen zamanında doğru türü dönecektir bir uzantısı yöntemi oluşturabilirsiniz Ben jenerik özgü IEnumerable<T> olmayan üzerinde sıralama yapmak için kullandıkları mekanizma ekledik genel IEnumerable

public static class SortingExtensions 
{ 
    public static IEnumerable<T> CustomSort<T>(this IEnumerable<T> source, string sortProperties) 
    { 
     // sort here 
    } 

    public static IEnumerable CustomSort(this IEnumerable source, string sortProperties) 
    { 
     var elementType = source.GetElementType(); 
     var genericElementType = typeof (IEnumerable<>).MakeGenericType(elementType); 

     var sortMethod = typeof (SortingExtensions).GetMethod(
      "CustomSort", 
      BindingFlags.Public | BindingFlags.Static, 
      null, 
      new [] {genericElementType, typeof (string)}, 
      null); 

     return (IEnumerable) sortMethod.Invoke(null, new object[] {source, sortProperties}); 
    } 

} 
+0

İlginç bir yaklaşım. Ben de denemeliyim. Sıralama yöntemi hakkında, bu, yaptığımız şeyden çok daha fazlasıdır, ancak her birinin kendine özgü yönleri olan birden fazla mülkle hesaplamayı da hesaba katıyoruz. –

+0

Çözümünüzü denedim, ancak enumerableType.GetGenericArguments(). First() bir StackOverflowException neden olur. (Bu yaşlardan bir tanesi yoktu! :)) –

+0

Sorunu buldum. Yöntem, genel statik IEnumerable CustomSort (bu IEnumerable kaynak, string sortProperties) üzerinden geçtikten sonra tekrar çağrılır ve bu sonsuz bir döngü oluşturur, ya da öyle görünüyor. –

1

Şahsen ben sadece

DataSource.Cast<object>() 

kullanmak ve sonra size CustomSort<T> işlevinde kullanabileceğiniz bir IEnumerable<object> var. Burada, bu işlevin zaten rastgele nesneleri ele alabileceğini farz ediyorum; ikinci parametre ismine göre karar vermekte olduğumu düşünmüyorum, yine de Reflection'ı kullanıyorsunuzdur, bu yüzden iyi olmalı. Sadece typeof(T)'a değil, her bir nesnenin GetType()'unu kullandığından emin olun, çünkü typeof(T) açıkça object olacaktır ve gerçek nesnenin alanlarının listesini alamaz. Tabii

, aslında derleme zamanında veri kaynağındaki tüm nesnelerin türünü biliyorsanız, bunun yerine bu tür kullanmak isteyebilirsiniz, örneğin:

DataSource.Cast<Customer>() 
+0

MoveNext() hakkında haklısınız. Bu yazıyı oluşturduğum zamana kadar zaten sildim, bu yüzden bellekten yazı yazıyordum. Oyuncu Hakkında <>, ben deneyeceğim. Teşekkür ederim! –

+0

@EladLachmi: Tamam, o zaman bu bölümü de sorunuzdan kaldırmaya özgür olacağım. – Timwi

+0

CustomSort işlevi, lambda ifadesi olarak sıralamayı oluşturmak için yansıma tipini (T) kullanır. Yeni bir şey yaratmayı (QA, vb., Vs, vs, vb. Ile gitmesi gerekecek) yaratmayı tercih ederim. Bunun nasıl yapıldığını bilirsin :)) –

4

burada temel bir sorun vardır Bir tür aynı anda birden çok T için IEnumerable-of-T uygulayabilir. Bavulu dışlamak Ama eğer, bir arsız bir yaklaşımdır:

void Evil<T>(IEnumerable<T> data) {...} 

IEnumerable source = ... 
dynamic cheeky = source; 
Evil(cheeky); 

Bu temelde Evil-of-T metodu sakin ol icar, DLR bu sorunu boşaltır.

public static class LinqExtensions 
{ 
    public static Type GetElementType(this IEnumerable source) 
    { 
     var enumerableType = source.GetType(); 
     if (enumerableType.IsArray) 
     { 
      return enumerableType.GetElementType(); 
     } 
     if (enumerableType.IsGenericType) 
     { 
      return enumerableType.GetGenericArguments().First(); 
     } 
     return null; 
    } 
} 

Güncelleme:

+1

Bu, 'source' aslında IEnumerable 'yi uygular. bazı 'T' için; .NET'teki birçok veri kaynağı, jenerikten önceki tarihlere dayanır ve bu nedenle aslında sadece IEnumerable özelliğini kullanır, bu durumda kodunuz bir "RuntimeBinderException" ile çöker. – Timwi

+0

@Timwi soru "döküm" hakkında sorar. Sadece bazı T. için genel sürümü uygularsa onu yayınlamak mümkün. Size katılmıyorum - sadece bu bağımlılığın söz konusu olduğunu söylüyorum. –

+0

@Timwi - Marc, jenerik olmayan IEnumerable'ın (DataSource) kökeninin, derleme zamanında bilinmeyen bazı T'nin bir List listesi olduğu varsayımında doğrudur.Böylece IEnumerable 'u uygulamalıdır. –

İlgili konular