2012-07-05 25 views
13

Ben .NET 2.0 veya 3.0 çalışma zamanı, ben hata alıyorum kullanarak bir uzantısı yöntemi eklemek deneyin:.NET 2.0 veya 3.0'da uzantı yöntemleri ve LINQ kullanabilir miyim?

Cannot define a new extension method because the compiler required type 'System.Runtime.CompilerServices.ExtensionAttribute' cannot be found. Are you missing a reference to System.Core.dll?

Ama denediğimde mevcut referanslar listesinde System.Core bulamıyorum projeye ekleyin. Projelerimde uzantı yöntemlerini kullanabilmek için LINQ açmak için ne yapmam gerekiyor?

cevap

28

Uzantı yöntemleri 3.5'e kadar .NET'e eklenmedi. Ancak, CLR'de bir değişiklik değildi, ancak onları ekleyen a change to the compiler, böylece bunları 2.0 ve 3.0 projelerinizde kullanabilirsiniz! Tek gereksinim, bu geçici çözümü yapabilmek için 3.5 proje oluşturabilen bir derleyiciye sahip olmanızdır (Visual   Studio   2008 ve üzeri).

Uzantı yöntemlerini kullanmaya gerek duymadığınızdan, bir uzantı yöntemini kullanmaya çalıştığınızda karşılaştığınız hata yanıltıcıdır, çünkü uzantı yöntemlerini kullanmak için gerçekten System.Core.dll gereksiniminiz yoktur. Bir uzantı yöntemi kullandığınızda, sahnelerin arkasında derleyici, işleve [Extension] özniteliğini ekliyor. [Extension] özniteliği ile ne yapacağını anlayan bir derleyiciniz varsa, özniteliği kendiniz oluşturuyorsanız, bunu 2.0 ve 3.0 projelerinizde kullanabilirsiniz.

Sadece projenize aşağıdaki sınıf eklemek ve daha sonra uzatma yöntemleri kullanarak başlayabilirsiniz:

namespace System.Runtime.CompilerServices 
{ 
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] 
    public class ExtensionAttribute : Attribute 
    { 
    } 
} 

Yukarıdaki kod bloğu hata diyor demek ki bu yüzden DLL dahil etmek gerekir System.Core.Dll içeride oturuyor bunları kullanmak için dosya.


Şimdi biraz daha fazla çalışma gerektiren LINQ işlevselliğini istiyorsanız. Uzantı yöntemlerini kendiniz yeniden uygulamanız gerekecektir. Tam LINQ to SQL işlevselliğini taklit etmek için kod oldukça karmaşık olabilir. Ancak, sadece LINQ to Objects kullanıyorsanız, çoğu LINQ yöntemi uygulamak zor değildir. İşte başlamanız için yazdığım bir projeden bazı LINQ   -   Nesneleri değiştirme işlevleri.

public static class LinqReplacement 
{ 
    public delegate TResult Func<T, TResult>(T arg); 
    public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2); 

    public static TSource First<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) 
    { 
     if (source == null) 
      throw new ArgumentNullException("source"); 
     if (predicate == null) 
      throw new ArgumentNullException("predicate"); 

     foreach (TSource item in source) 
     { 
      if (predicate(item) == true) 
       return item; 
     } 

     throw new InvalidOperationException("No item satisfied the predicate or the source collection was empty."); 
    } 

    public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source) 
    { 
     if (source == null) 
      throw new ArgumentNullException("source"); 

     foreach (TSource item in source) 
     { 
      return item; 
     } 

     return default(TSource); 
    } 

    public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source) 
    { 
     foreach (object item in source) 
     { 
      yield return (TResult)item; 
     } 
    } 

    public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector) 
    { 
     if (source == null) 
      throw new ArgumentNullException("source"); 
     if (selector == null) 
      throw new ArgumentNullException("selector"); 

     foreach (TSource item in source) 
     { 
      foreach (TResult subItem in selector(item)) 
      { 
       yield return subItem; 
      } 
     } 
    } 

    public static int Count<TSource>(this IEnumerable<TSource> source) 
    { 
     var asCollection = source as ICollection; 
     if(asCollection != null) 
     { 
      return asCollection.Count; 
     } 

     int count = 0; 
     foreach (TSource item in source) 
     { 
      checked //If we are counting a larger than int.MaxValue enumerable this will cause a OverflowException to happen when the counter wraps around. 
      { 
       count++; 
      } 
     } 
     return count; 
    } 
} 

zaten ilave ExtensionAttribute ile   LINQ nesnelere   tam yeniden implemenation ile bir kütüphane

LinqBridge projesi (teşekkürler Allon Guralnek) bulunabilir.

+0

LinqReplacement yöntemlerinin yalnızca Linq to Objects için çalışacağını belirtmek önemlidir. Linq'den Sql'ye çalışmayacak. Birçok insanın fark olduğunu farketmemiş gibi görünüyor. Fakat yine de +1 – cadrell0

+0

Uzantı yöntemlerini kendiniz tekrar uygulamanız gerekmez. Eksiksiz LINQ'dan Nesneler sağlayıcıya çoktan bir süre önce .NET 2.0 için [LinqBridge] (http://linqbridge.googlecode.com/) olarak yeniden uygulandı. Ve zaten VS 2008 ve üstü ile .NET 2.0'da uzantı yöntemleri oluşturmanıza olanak sağlayan 'ExtensionAttribute' öğesini de içerir. –

+0

@ AllonGuralnek Bağlantı için teşekkürler, cevabı güncelledi ve size kredi verdi. –