Методы расширения не добавлялись в .NET до версии 3.5. Однако это было не изменение CLR, а изменение компилятора, добавил их, так что вы все еще можете использовать их в своих проектах 2.0 и 3.0! Единственное требование - у вас должен быть компилятор, который может создавать проекты 3.5, чтобы иметь возможность делать это обходное решение (Visual Studio 2008 и выше).
Ошибка, которую вы получаете, когда пытаетесь использовать метод расширения, вводит в заблуждение, поскольку вам действительно не нужно System.Core.dll
использовать методы расширения. Когда вы используете метод расширения, за кулисами компилятор добавляет _ 2_ функции. Если у вас есть компилятор, который понимает, что делать с атрибутом [Extension]
, вы можете использовать его в своих проектах 2.0 и 3.0, если создадите атрибут самостоятельно.
Просто добавьте в свой проект следующий класс, и вы сможете начать использовать методы расширения:
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class ExtensionAttribute : Attribute
{
}
}
Приведенный выше блок кода находится внутри System.Core.Dll, поэтому в сообщении об ошибке говорится, что для их использования необходимо включить файл DLL.
Теперь, если вам нужна функциональность LINQ, это потребует немного дополнительной работы. Вам нужно будет заново реализовать методы расширения самостоятельно. Чтобы имитировать полную функциональность LINQ to SQL, код может стать довольно сложным. . Однако, если вы просто используете LINQ to Objects, большинство методов LINQ не сложно реализовать. Вот несколько функций замены LINQ to Objects из проекта, который я написал для начала.
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;
}
}
Библиотеку с полной повторной реализацией LINQ to Objects с уже добавленным ExtensionAttribute
можно найти в Проект LinqBridge (спасибо, Аллону Гуралнеку).
person
Scott Chamberlain
schedule
05.07.2012