2012-07-05 8 views
13

Cuando intento agregar un método de extensión utilizando .NET 2.0 o 3.0 en tiempo de ejecución, me sale el error:¿Puedo usar métodos de extensión y LINQ en .NET 2.0 o 3.0?

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?

Pero no puedo encontrar System.Core en la lista de referencias disponibles cuando intento agrégalo al proyecto. ¿Qué debo hacer para poder usar los métodos de extensión y, a su vez, LINQ en mis proyectos?

Respuesta

28

Los métodos de extensión no se agregaron a .NET hasta 3.5. Sin embargo, no fue un cambio en el CLR, sino a change to the compiler que los agregó, por lo que aún puede usarlos en sus proyectos 2.0 y 3.0. El único requisito es que debe tener un compilador que pueda crear proyectos de 3.5 para poder realizar esta solución alternativa (Visual   Studio   2008 y superior).

El error que obtiene cuando intenta utilizar un método de extensión es engañoso, ya que realmente no necesita System.Core.dll para utilizar los métodos de extensión. Cuando utiliza un método de extensión, detrás de las escenas, el compilador agrega el atributo [Extension] a la función. Si tiene un compilador que entiende qué hacer con el atributo [Extension], puede usarlo en sus proyectos 2.0 y 3.0 si crea el atributo usted mismo.

Apenas añada la siguiente clase a su proyecto y, a continuación, puede empezar a utilizar métodos de extensión:

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

El bloque de código anterior está sentado en el interior System.Core.Dll, así que por eso dice que el error es necesario incluir la DLL archivo para usarlos.


Ahora, si desea la funcionalidad LINQ, necesitará un poco más de trabajo. Tendrá que volver a implementar los métodos de extensión usted mismo. Para imitar la funcionalidad completa de LINQ to SQL, el código puede ser bastante complicado. Sin embargo, si solo está usando LINQ to Objects, la mayoría de los métodos LINQ no son complicados de implementar. Aquí hay algunos LINQ   a   Funciones de reemplazo de objetos de un proyecto que escribí para comenzar.

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

Una biblioteca con la re-implemenation llena de LINQ     a objetos con el ExtensionAttribute ya añadido en se pueden encontrar en la LinqBridge proyecto (Allon Guralnek Gracias).

+0

Es importante señalar que sus métodos LinqReplacement solo funcionarán para Linq to Objects. No funcionará para Linq a Sql. Parece que mucha gente no se da cuenta de que hay una diferencia. Pero todavía +1 – cadrell0

+0

No tiene que volver a implementar los métodos de extensión usted mismo. El proveedor completo de LINQ-a-Objetos ya se ha reimplementado para .NET 2.0 hace mucho tiempo como [LinqBridge] (http://linqbridge.googlecode.com/). Y ya incluye el 'ExtensionAttribute' que le permite crear métodos de extensión en .NET 2.0 con VS 2008 y superior. –

+0

@AllonGuralnek Gracias por el enlace, actualizó la respuesta y le dio crédito. –

Cuestiones relacionadas