Phương thức mở rộng không được thêm vào .NET cho đến 3.5. Tuy nhiên, nó không phải là một thay đổi đối với CLR, nhưng a change to the compiler đã thêm chúng, vì vậy bạn vẫn có thể sử dụng chúng trong các dự án 2.0 và 3.0 của mình! Yêu cầu duy nhất là bạn phải có trình biên dịch có thể tạo 3,5 dự án để có thể thực hiện giải pháp này (Visual Studio năm 2008 trở lên).
Lỗi bạn nhận được khi bạn cố gắng sử dụng một phương pháp tiện ích là gây hiểu lầm vì bạn không thực sự cần System.Core.dll
để sử dụng các phương pháp mở rộng. Khi bạn sử dụng một phương thức mở rộng, đằng sau hậu trường, trình biên dịch sẽ thêm thuộc tính [Extension]
vào hàm. Nếu bạn có trình biên dịch hiểu được việc cần làm với thuộc tính [Extension]
, bạn có thể sử dụng nó trong các dự án 2.0 và 3.0 nếu bạn tự tạo thuộc tính.
Chỉ cần thêm lớp sau vào dự án của bạn và sau đó bạn có thể bắt đầu sử dụng phương pháp khuyến nông:
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class ExtensionAttribute : Attribute
{
}
}
Khối mã trên đang ngồi bên System.Core.Dll, vì vậy đó là lý do tại sao những lỗi nói rằng bạn cần phải bao gồm các DLL để sử dụng chúng.
Bây giờ nếu bạn muốn chức năng LINQ sẽ tốn thêm một chút công sức. Bạn sẽ cần phải tự triển khai lại các phương thức mở rộng. Để bắt chước chức năng đầy đủ của LINQ to SQL, mã có thể khá phức tạp. Tuy nhiên, nếu bạn chỉ sử dụng LINQ to Objects hầu hết các phương pháp LINQ không phức tạp để thực hiện. Dưới đây là một vài LINQ đến Các chức năng thay thế đối tượng từ một dự án mà tôi đã viết ra để giúp bạn bắt đầu.
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;
}
}
Một thư viện với đầy đủ tái implemenation của LINQ - Objects với ExtensionAttribute
đã được thêm vào trong có thể được tìm thấy trong các dự án LinqBridge (Cảm ơn Allon Guralnek).
Điều quan trọng là chỉ ra rằng các phương pháp LinqReplacement của bạn sẽ chỉ hoạt động cho LINQ to Objects. Nó sẽ không hoạt động cho LINQ to Sql. Có vẻ như rất nhiều người không nhận ra có sự khác biệt. Nhưng vẫn +1 – cadrell0
Bạn không phải tự triển khai lại các phương thức tiện ích. Nhà cung cấp LINQ-to-Objects hoàn chỉnh đã được triển khai lại cho .NET 2.0 từ lâu như [LinqBridge] (http://linqbridge.googlecode.com/). Và nó đã bao gồm 'ExtensionAttribute' cho phép bạn tạo các phương thức mở rộng trong .NET 2.0 với VS 2008 trở lên. –
@AllonGuralnek Cảm ơn bạn đã liên kết, cập nhật câu trả lời và cho bạn tín dụng. –