2012-05-07 9 views
5

मैं एक त्वरित कक्षा बनाने की कोशिश कर रहा हूं ताकि मैं ग्रिड के लिए लेखन सॉर्टिंग कोड बना सकूं और बनाए रख सकूं और कोड दोहराव रख सकूं। ऐसा करने के लिए मैं निम्नलिखित वर्ग के साथ आया था:मैं लिंक ऑर्डरबी के लिए उपयोग की जाने वाली अभिव्यक्तियों को गतिशील रूप से कैसे संग्रहीत कर सकता हूं?

public class SortConfig<TSource, TRelatedObject> where TSource : class where TRelatedObject : class 
{ 
    public IList<SortOption> Options { get; protected set; } 
    public SortOption DefaultOption { get; set; } 

    public SortConfig() 
    { 
     Options = new List<SortOption>(); 
    } 

    public void Add(string name, Expression<Func<TSource, object>> sortExpression, TRelatedObject relatedObject, bool isDefault = false) 
    { 
     var option = new SortOption 
     { 
      FriendlyName = name, 
      SortExpression = sortExpression, 
      RelatedObject = relatedObject 
     }; 

     Options.Add(option); 

     if (isDefault) 
      DefaultOption = option; 
    } 

    public SortOption GetSortOption(string sortName) 
    { 
     if (sortName.EndsWith("asc", StringComparison.OrdinalIgnoreCase)) 
      sortName = sortName.Substring(0, sortName.LastIndexOf("asc", StringComparison.OrdinalIgnoreCase)); 
     else if (sortName.EndsWith("desc", StringComparison.OrdinalIgnoreCase)) 
      sortName = sortName.Substring(0, sortName.LastIndexOf("desc", StringComparison.OrdinalIgnoreCase)); 

     sortName = sortName.Trim(); 

     var option = Options.Where(x => x.FriendlyName.Trim().Equals(sortName, StringComparison.OrdinalIgnoreCase)) 
          .FirstOrDefault(); 
     if (option == null) 
     { 
      if (DefaultOption == null) 
       throw new InvalidOperationException(
        string.Format("No configuration found for sort type of '{0}', and no default sort configuration exists", sortName)); 

      option = DefaultOption; 
     } 

     return option; 
    } 

    public class SortOption 
    { 
     public string FriendlyName { get; set; } 
     public Expression<Func<TSource, object>> SortExpression { get; set; } 
     public TRelatedObject RelatedObject { get; set; } 
    } 
} 

विचार है कि आप अलग अलग तरह के विकल्प, क्या अभिव्यक्ति orderBy की एक त्वरित विन्यास बनाने के लिए प्रयोग किया जाता है, और वैकल्पिक रूप से एक उद्देश्य यह है कि कि से संबंधित है सॉर्ट विकल्प। यह मेरा कोड की तरह लग रहे करने के लिए अनुमति देता है:

protected void InitSortConfig() 
    { 
     _sortConfig = new SortConfig<xosPodOptimizedSearch, HtmlAnchor>(); 
     _sortConfig.Add("name", (x => x.LastName), lnkSortName, true); 
     _sortConfig.Add("team", (x => x.SchoolName), lnkSortTeam); 
     _sortConfig.Add("rate", (x => x.XosRating), lnkSortRate); 
     _sortConfig.Add("pos", (x => x.ProjectedPositions), null); 
     _sortConfig.Add("height", (x => x.Height), lnkSortHeight); 
     _sortConfig.Add("weight", (x => x.Weight), lnkSortWeight); 
     _sortConfig.Add("city", (x => x.SchoolCity), lnkSortCity); 
     _sortConfig.Add("state", (x => x.SchoolState), lnkSortState); 
    } 

और फिर मैं सिर्फ

 // Get desired sorting configuration 
     InitSortConfig(); 
     var sortOption = _sortConfig.GetSortOption(sort); 
     bool isDescendingSort = sort.EndsWith("desc", StringComparison.OrdinalIgnoreCase); 

     // Setup columns 
     InitSortLinks(); 
     if (sortOption.RelatedObject != null) 
     { 
      // Make modifications to html anchor 
     } 

     // Form query 
     var query = PodDataContext.xosPodOptimizedSearches.AsQueryable(); 

     if (isDescendingSort) 
      query = query.OrderByDescending(sortOption.SortExpression); 
     else 
      query = query.OrderBy(sortOption.SortExpression); 

कर यह महान काम करता है जब क्रमबद्ध चर एक स्ट्रिंग है द्वारा सॉर्ट कर सकते हैं, लेकिन जब यह एक स्ट्रिंग मैं नहीं है निम्नलिखित अपवाद: Cannot order by type 'System.Object'.

मुझे लगता है कि ऐसा इसलिए है क्योंकि मैं अभिव्यक्ति को Expression<Func<TSource, object>> के रूप में संग्रहीत कर रहा हूं और उस दूसरे जेनेरिक के बारे में अधिक विशिष्ट नहीं हूं। मुझे समझ में नहीं आता कि मैं एक वर्ग में अपने सभी अलग-अलग प्रकार के विकल्पों (यहां तक ​​कि गैर-स्ट्रिंग गुणों के लिए भी) रख सकता हूं।

मैं मुद्दों में से एक लगता है कि Linq.OrderBy() खंड Expression<Func<TSource, TKey>> लेता है के रूप में यह पैरामीटर है है, लेकिन मैं चारों ओर कैसे Linq.OrderBy() अनुमान लगाने के लिए क्या TKey होना चाहिए में सक्षम है मेरे सिर लपेटकर नहीं कर रहा हूँ, और इसलिए मैं नहीं समझ सकता का लाभ लेने के लिए कैसे इन अभिव्यक्तियों को उचित TKey के साथ स्टोर करने का अनुमान है।

कोई विचार?

+0

[इस] पर एक नजर डालें (http://weblogs.asp.net/scottgu/archive/2008/01 /07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx) – Nestor

+0

धन्यवाद, लेकिन मैं सॉर्टिंग निर्दिष्ट स्ट्रिंग के बजाय कोड-निर्दिष्ट होना चाहूंगा, खासकर जब से मेरी डेटा संरचना ग्रिड मेरे डेटाबेस के साथ 1: 1 डेटा मॉडल नहीं है, इसलिए सॉर्ट को ग्रिड-निर्दिष्ट से डीबी सॉर्ट में अनुवादित करने की आवश्यकता है, फिर भी – KallDrexx

+0

क्या आप किसी भी प्रकार का सॉर्ट विकल्प प्राप्त करते समय जादू स्ट्रिंग का उपयोग नहीं कर रहे हैं? –

उत्तर

5

सामान्य तर्क इसलिए की तरह मान लिया जाता है:

IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> enumerable, Func<TSource, TKey> expression) 

जब आप एक IEnumerable<T> है, संकलक अनुमान लगाने के लिए कि TSource विस्तार विधि घोषणा की वजह से इस स्थिति में T है में सक्षम है; तो TSource क्या है यह जानने के लिए एक्सटेंशन विधि पहले से ही जोड़ दी गई है। उदाहरण के लिए:

Enumerable.Range(0, 10).OrderBy(x => x) 

जब से हम एक IEnumerable<int> के साथ शुरू, संकलक अनुमान लगा सकते हैं कि अभिव्यक्ति यह उम्मीद Func<int, TKey> है, क्योंकि विस्तार IEnumerable<int> प्रभावित कर रहा है। अगला, क्योंकि आपकी अभिव्यक्ति एक मान देता है, इसलिए संकलक शेष स्थिति का अनुमान लगा सकता है, इस स्थिति में int, इसलिए यह इस उदाहरण के साथ Func<int, int> बन जाता है।

अब, आपकी विशेष समस्या के लिए जर्मनी, यदि आप अपने SortConfig ऑब्जेक्ट को उचित रूप से जेनरेट करते हैं तो आप आसानी से काम करने के लिए अपनी अभिव्यक्ति सेट कर सकते हैं। ऐसा लगता है कि आपके SortConfig अभी Func<TSource, object> प्रतिनिधि हैं। यदि आप किसी अन्य प्रकार का उपयोग करने के लिए अपने SortConfig जेनेरिक करते हैं, तो आप विशिष्टता प्राप्त करते हैं। उदाहरण:

void Add<TSource, TKey>(string name, Func<TSource, TKey> expression) 

अगली समस्या यह है कि कुछ प्रारूप में अपनी बैकिंग विधियों को कैसे स्टोर किया जाए। और अपनी कक्षा घोषणा तो की तरह दिखता है:

public class SortConfig<TSource> 

तब सभी डेटा प्रकार लाइन अप जब आप OrderBy विस्तार आह्वान करना चाहिए।

संपादित करें: यहाँ मैं क्या लगता है कि आप क्या करना चाहते हैं की एक काम उदाहरण है:

static void Main(string[] args) 
    { 
     var list = Enumerable.Range(0, 10).Reverse().Select(x => new SampleClass { IntProperty = x, StringProperty = x + "String", DateTimeProperty = DateTime.Now.AddDays(x * -1) }); 

     SortContainer<SampleClass> container = new SortContainer<SampleClass>(); 
     container.Add("Int", x => x.IntProperty); 
     container.Add("String", x => x.StringProperty); 
     container.Add("DateTime", x => x.DateTimeProperty); 

     var sorter = container.GetSorterFor("Int"); 

     sorter.Sort(list).ForEach(x => Console.WriteLine(x.IntProperty)); 
     Console.ReadKey(); 
    } 

    public class SampleClass 
    { 
     public int IntProperty { get; set; } 
     public string StringProperty { get; set; } 
     public DateTime DateTimeProperty { get; set; } 
    } 

    public class SortContainer<TSource> 
    { 
     protected Dictionary<string, ISorter<TSource>> _sortTypes = new Dictionary<string, ISorter<TSource>>(); 

     public void Add<TKey>(string name, Func<TSource, TKey> sortExpression) 
     { 
      Sorter<TSource, TKey> sorter = new Sorter<TSource, TKey>(sortExpression); 
      _sortTypes.Add(name, sorter); 
     } 

     public ISorter<TSource> GetSorterFor(string name) 
     { 
      return _sortTypes[name]; 
     } 
    } 

    public class Sorter<TSource, TKey> : ISorter<TSource> 
    { 
     protected Func<TSource, TKey> _sortExpression = null; 

     public Sorter(Func<TSource, TKey> sortExpression) 
     { 
      _sortExpression = sortExpression; 
     } 

     public IOrderedEnumerable<TSource> Sort(IEnumerable<TSource> sourceEnumerable) 
     { 
      return sourceEnumerable.OrderBy(_sortExpression); 
     } 
    } 

    public interface ISorter<TSource> 
    { 
     IOrderedEnumerable<TSource> Sort(IEnumerable<TSource> sourceEnumerable); 
    } 
+0

मैं इस प्रकार से कहां जा रहा हूं कि आप कहां जा रहे हैं, लेकिन यह 'शून्य' 'जोड़ें 'विधि क्या है? क्या आपका मतलब है '_sortConfig.Add'? –

+0

हाँ, मुझे वास्तव में पता नहीं था कि आपकी विधि हस्ताक्षर क्या है, इसलिए मुझे इस पर विचार करना पड़ा। – Tejs

+0

यह समझ में आता है, सिवाय इसके कि मुझे यह नहीं पता कि 'एक्सप्लोरेशन .ortExpression' प्रॉपर्टी को मेरी अभिव्यक्तियों को संग्रहीत करने के लिए किस प्रकार को देना है – KallDrexx

संबंधित मुद्दे

 संबंधित मुद्दे