วิธีการขยายไม่ได้ถูกเพิ่มลงใน .NET จนถึง 3.5 อย่างไรก็ตาม ไม่ใช่การเปลี่ยนแปลง CLR แต่ การเปลี่ยนแปลงคอมไพเลอร์ที่ เพิ่มเข้าไปแล้ว ดังนั้นคุณยังคงสามารถใช้มันในโครงการ 2.0 และ 3.0 ของคุณได้! ข้อกำหนดเพียงอย่างเดียวคือคุณต้องมีคอมไพเลอร์ที่สามารถสร้างโปรเจ็กต์ 3.5 เพื่อให้สามารถแก้ไขปัญหานี้ได้ (Visual Studio 2008 ขึ้นไป)
ข้อผิดพลาดที่คุณได้รับเมื่อคุณพยายามใช้วิธีการขยายทำให้เข้าใจผิด เนื่องจากคุณไม่จำเป็นต้องใช้ System.Core.dll
จริงๆ เพื่อใช้วิธีการขยาย เมื่อคุณใช้วิธีการขยาย เบื้องหลัง คอมไพเลอร์กำลังเพิ่ม [Extension]
แอตทริบิวต์ของฟังก์ชัน หากคุณมีคอมไพเลอร์ที่เข้าใจว่าต้องทำอย่างไรกับแอตทริบิวต์ [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 ให้กับออบเจ็กต์ใหม่ทั้งหมดโดยเพิ่ม ExtensionAttribute
เข้าไปแล้วสามารถพบได้ใน โครงการ LinqBridge (ขอขอบคุณ Allon Guralnek)
person
Scott Chamberlain
schedule
05.07.2012