2012-07-05 31 views
13

जब मैं नेट 2.0 या 3.0 क्रम, मैं त्रुटि मिलती है का उपयोग कर एक विस्तार विधि को जोड़ने का प्रयास:क्या मैं .NET 2.0 या 3.0 में एक्सटेंशन विधियों और LINQ का उपयोग कर सकता हूं?

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?

लेकिन मैं System.Core उपलब्ध संदर्भ की सूची में नहीं मिल सकता है जब मैं करने की कोशिश इसे परियोजना में जोड़ें। विस्तार परियोजनाओं का उपयोग करने में सक्षम होने के लिए मुझे क्या करना चाहिए और बदले में LINQ मेरी परियोजनाओं में?

उत्तर

28

एक्सटेंशन विधियों को 3.5 तक .NET में नहीं जोड़ा गया था। हालांकि, यह सीएलआर में कोई बदलाव नहीं था, लेकिन a change to the compiler ने उन्हें जोड़ा, ताकि आप अभी भी उन्हें 2.0 और 3.0 परियोजनाओं में उपयोग कर सकें! एकमात्र आवश्यकता यह है कि आपके पास एक कंपाइलर होना चाहिए जो इस कार्यवाही को करने में सक्षम होने के लिए 3.5 परियोजनाएं बना सकता है (दृश्य   स्टूडियो   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   से   ऑब्जेक्ट्स प्रतिस्थापन फ़ंक्शंस हैं जिन्हें मैंने शुरू करने के लिए लिखा था।

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

पूर्ण ExtensionAttribute पहले से ही में जोड़ा साथ   वस्तुओं के लिए LINQ   की फिर से implemenation के साथ एक पुस्तकालय LinqBridge परियोजना (Allon Guralnek धन्यवाद) में पाया जा सकता है।

+0

यह इंगित करना महत्वपूर्ण है कि आपके लिंक रिकिप्लेसमेंट विधियां केवल लिंक से ऑब्जेक्ट्स के लिए काम करेंगी। यह लिंक से एसक्यूएल के लिए काम नहीं करेगा। ऐसा लगता है कि बहुत से लोगों को यह नहीं पता कि कोई अंतर है। लेकिन अभी भी +1 – cadrell0

+0

आपको एक्सटेंशन विधियों को फिर से कार्यान्वित करने की आवश्यकता नहीं है। पूर्ण LINQ-to-Objects प्रदाता पहले से ही .NET 2.0 के लिए [LinqBridge] (http://linqbridge.googlecode.com/) के रूप में फिर से कार्यान्वित किया जा चुका है। और इसमें पहले से ही 'एक्सटेंशन एट्रिब्यूट' शामिल है जो आपको वीएस 2008 और उसके बाद .NET 2.0 में एक्सटेंशन विधियां बनाने की अनुमति देता है। –

+0

@AllonGuralnek लिंक के लिए धन्यवाद, उत्तर अपडेट किया गया और आपको क्रेडिट दिया। –