2011-12-27 12 views
5

में एक selectList उत्पन्न मैं निम्नलिखित दो तरीकों कि मेरे DB से डेटा प्राप्त है और एक आबादी वाले selectList वस्तु (एक "सभी" विकल्प मान सहित) लौटने कि मैं तो मेरे विचार पर पारित किया है। समस्या यह है कि वे अपवाद के लगभग समान हैं कि वे दोनों अलग-अलग भंडार वस्तुओं तक पहुंचते हैं और उनके पास अलग-अलग आईडी नाम हैं (StatusId और TeamId)। मुझे लगता है कि उन्हें एक ऐसी विधि में दोबारा करने का अवसर है जो रिपॉजिटरी को पैरामीटर के रूप में स्वीकार करता है और किसी भी तरह से आईडी नाम होना चाहिए, शायद प्रतिबिंब या किसी प्रकार का लैम्ब्डा अभिव्यक्ति का उपयोग करके, लेकिन मुझे नहीं पता कि कैसे यह प्राप्त करने के।Refactor दो विधियों है कि एक ही विधि

private SelectList GetStatusSelectList(int selectedStatusId) 
{ 
    List<MemberStatus> statusList = _memberStatusRepository.All().ToList(); 
    statusList.Insert(0, new MemberStatus {StatusId = 0, Name = "All"}); 
    var statusSelectList = new SelectList(statusList, "StatusId", "Name", selectedStatusId); 
    return statusSelectList; 
} 

private SelectList GetTeamSelectList(int selectedTeamId) 
{ 
    List<MemberTeam> teamList = _memberTeamRepository.All().ToList(); 
    teamList.Insert(0, new MemberTeam { TeamId = 0, Name = "All" }); 
    var teamSelectList = new SelectList(teamList, "TeamId", "Name", selectedTeamId); 
    return teamSelectList; 
} 

कैसे एक एकल विधि में इन refactor करने के लिए किसी को भी मदद आंकड़ा बाहर कर सकते हैं?

+1

आप उन वर्गों अर्थात एक अंतरफलक जोड़ने संपादित करने में सक्षम हैं? –

+0

हाँ ... दोनों _memberTeamRepostiory और _memberStatusRepository एक IRepository इंटरफ़ेस को लागू। यही कारण है कि इंटरफेस सभी IQueryable सभी() जो केवल दिया TEntity की _dbSet रिटर्न की तरह उपाय अपना सकते हैं डीबी के साथ बातचीत करने के तरीकों है। – bigmac

+0

सदस्य टीम और सदस्यस्टैटस के बारे में - क्या आप उन्हें सीधे या आंशिक कक्षाओं के साथ संशोधित कर सकते हैं? – foson

उत्तर

2

आप निम्नलिखित कोशिश कर सकते हैं:

private SelectList GetStatusSelectList(int selectedStatusId) 
{ 
    return GetGenericSelectList<MemberStatus>(selectedStatusId, _memberStatusRepository.All().ToList(), "StatusId"); 
} 

private SelectList GetTeamSelectList(int selectedTeamId) 
{ 
    return GetGenericSelectList<MemberTeam>(selectedTeamId, _memberTeamRepository.All().ToList(), "TeamId"); 
} 

private SelectList GetGenericSelectList<T>(int selectedTeamId, List<T> list, string idFieldName) where T : new() 
{ 
    var firstItem = new T(); 
    (firstItem as dynamic).Name = "All"; 
    var l = new List<T>(list); 
    l.Insert(0, firstItem); 
    return new SelectList(l, idFieldName, "Name", selectedTeamId); 
} 

यह समाधान आदर्श नहीं है और कुछ परंपराओं पर निर्भर करता है (उदाहरण के लिए अपने सभी आइटम Name संपत्ति होनी चाहिए)। हालांकि यह शुरू करने के लिए एक बुरा रास्ता नहीं लगता है। इसे संपत्ति नामों के बजाय अभिव्यक्तियों का उपयोग करके आगे बढ़ाया जा सकता है - जो संकलन समय जांच के साथ संपत्ति के नाम बदलने की अनुमति देगा।

+0

कोड के लिए धन्यवाद। ऐसा लगता है, लेकिन मेरे पास आपके लिए दो प्रश्न हैं। सबसे पहले, मैंने आपके कोड की तीसरी और चौथी पंक्तियां हटा दीं और बस 'सूची' का उपयोग किया। इसके बजाय (0, firstItem) प्रविष्ट करें। क्या इसमें कोई समस्या है? दूसरा, मुझे नहीं पता कि 'टी: नया()' विधि हस्ताक्षर में कहां है। क्या आप मुझे बता सकते हैं कि यह क्या कर रहा है? – bigmac

+0

मैं तर्क से एक नई सूची बनाता हूं, क्योंकि अन्यथा मौजूदा सूची संशोधित की जाएगी (आप एक मौजूदा सूची पास करते हैं और फ़ंक्शन इसमें एक नया तत्व डालता है)। यह कोई मुद्दा नहीं हो सकता है, लेकिन क्या होगा यदि उस मूल सूची का उपयोग इस विधि के बगल में कहीं और किया जाता है? नई बाधा के बारे में - यह सिर्फ 'नया टी() 'करने की अनुमति देता है। अधिक जानकारी के लिए http://msdn.microsoft.com/en-us/library/sd2w2ew5.aspx देखें। –

+1

यह मेरी तत्काल जरूरतों का सबसे साफ समाधान है, इसलिए धन्यवाद! – bigmac

3

खैर, यह सबसे सामान्य मैं के साथ आ सकता है, लेकिन यह आवश्यक होगा कि आपके MemberStatus और MemberTeamIIdentifiable है, जो मैं नहीं जानता कि लागू करता है, तो अपने मामले के लिए आवेदन कर सकते हैं। यदि ऐसा है, तो यह जाने का रास्ता होगा।

private SelectList GetList<T>(IRepository repository, int id, string name) 
    where T : IIdentifiable, new() 
{ 
    List<IIdentifiable> list = repository.All().ToList(); 
    list.Insert(0, new T() { Name = name, Id = id }); 
    var statusSelectList = new SelectList(list, "Id", "Name", id); 
} 

और इंटरफ़ेस कोड

interface IIdentifiable 
{ 
    int Id { get; set; } 
    string Name { get; set; } 
} 
+0

धन्यवाद टॉमस्लाव। हालांकि, एक चिंता हालांकि, सदस्य टीम और सदस्यस्टैटस के लिए मेरे पीओसीओ ऑब्जेक्ट्स बहुत ही सरल हैं और दोनों के पास नाम संपत्ति है, लेकिन प्रत्येक के पास आईडी प्रॉपर्टी (स्टेटसआईडी और टीमआईडी) के लिए एक अद्वितीय नाम है। क्या इन गुणों को नामित रखने का कोई तरीका है और अभी भी आपके द्वारा वर्णित इंटरफ़ेस को लागू किया गया है? मुझे डीबी डिज़ाइन के लिए नाम अधिक वर्णनात्मक होना पसंद है, लेकिन इसकी अनुशंसा की जाने पर केवल आईडी के अधिक सामान्य क्षेत्र का उपयोग करने के लिए राजी किया जा सकता है। – bigmac

+0

बेशक, बस अपनी कक्षाओं में 'IIDentifiable.Id' संपत्ति को 'StatusId' और' TeanId' पर मानचित्र करें। 'int आईडी {{वापसी स्थिति आईडी प्राप्त करें; } सेट {StautsId = मान; }} 'आपके 'सदस्यस्टैटस' कक्षा में। क्या यह काम नहीं करेगा? –

+1

@ टॉमस्लावा ... इसके लिए धन्यवाद। मैं foson को, जो इसी तरह के कुछ पोस्ट उल्लेख किया है, मैं अपने डोमेन मॉडल की एक और अधिक मजबूत पुनर्रचना के लिए अपने विधि का उपयोग करने के लिए जा रहा हूँ, लेकिन the_joric का जवाब सवाल मैं पोस्ट के लिए सबसे अधिक संक्षिप्त है, इसलिए मैं अपने पद को स्वीकार करने के लिए जा रहा हूँ । लेकिन फिर, इनपुट के लिए धन्यवाद और आपने मुझे इस परियोजना को जारी रखने के लिए कुछ नए दिशानिर्देश दिखाए हैं! – bigmac

1

मैं क्या देख से, एक भी विधि में इस पुनर्रचना के रास्ते में मुख्य बाधा दौड़ new MemberStatus और new MemberTeam कॉल, इसके अलावा में सही का निर्धारण करने के लिए कर रहे उपयोग करने के लिए भंडार।

एक सुरुचिपूर्ण समाधान के साथ आने के लिए, आपको थोड़ा और बुनियादी ढांचा कॉन्फ़िगर करने की आवश्यकता होगी - मूल रूप से आपको इस प्रकार के आधार पर सही भंडार को हल करने की आवश्यकता होगी और आप किसी प्रकार का कारखाना ऑब्जेक्ट इंस्टेंस बनाना चाहते हैं।

निम्नलिखित एक भी विधि में कोड refactor होगा, लेकिन (मेरी राय में) नहीं है अलग तरीकों की तुलना में किसी भी बेहतर आपके पास पहले से:

private SelectList GetSelectList<T>(int selectedId, Func<List<T>> repoAllFunc, Func<T> typeNewFunc, string idName) 
{ 
    List<T> list = repoAllFunc(); 
    list.Insert(0, typeNewFunc()); 
    var selectList = new SelectList(list, idName, "Name", selectedId); 
    return selectList; 
} 

फिर आप इसे इस तरह कह सकते हैं:

var memberStatusSelectList = 
    GetSelectList<MemberStatus>(
     id, 
     () => _memberStatusRepository.All().ToList(), 
     () => new MemberStatus {StatusId = 0, Name = "All"}); 
+0

एथन, मैं आपके कोड को भी कोशिश कर रहा हूं, लेकिन आपकी विधि को कॉल करने का तरीका समझने में कठिन समय है। मुझे लगता है कि यह एक लैम्ब्डा अभिव्यक्ति लेता है, लेकिन चूंकि मैं इनके लिए नया हूं, क्या आप मुझे एक पॉइंटर दे सकते हैं जो मैं Func <> पैरामीटर के लिए पास करता हूं? – bigmac

+0

@bmccleary मैंने उपयोग करने का एक उदाहरण जोड़ा। इस उदाहरण में funcs कोई पैरामीटर नहीं लेते हैं इसलिए वाक्यविन्यास उतना सरल है जितना प्रतिनिधि प्रतिनिधि वाक्य के लिए मिलता है। अन्यथा, वे थोड़ा उलझन मिलता है। –

+0

नमूना कोड और स्पष्टीकरण के लिए धन्यवाद। मैं अब के लिए the_joric के जवाब को स्वीकार करने के रूप में यह मेरी तत्काल जरूरतों के लिए एक छोटे से क्लीनर है जा रहा हूँ, लेकिन मैं यह पता लगाने की कैसे थोड़ी देर के लिए तरीकों में प्रतिनिधियों पारित करने के लिए, और अपने नमूना मुझे कैसे के लिए यह करने के लिए पर कुछ दिशा प्रदान कोशिश कर रहे हैं मेरे कोड के अन्य क्षेत्रों, तो बहुत बहुत धन्यवाद! – bigmac

0

यदि IRepository कुछ "विशेषताएं" जोड़ता है, तो आपको कुछ क्लीनर कोड मिल जाएगा।

All() के बजाय SingleRecordsWithAllRecord() विधि है जो पहले दो पंक्तियों को संभालती है। फिर भंडार अपने DataValueField और DataTextField परिभाषित करता है।

private SelectList GetSelectList(IRepository repo, int selectedId) 
{ 
    var selectListAll = repo.SingleRecordsWithAllRecord().ToList(); 

    return new SelectList(selectListAll, 
         repo.DataValueField, 
         repo.DataTextField, 
         selectedId); 
} 
+0

ऑस्टिन, मैं अपने विचार पैटर्न यहाँ पसंद है, और मुझे लगता है कि के रूप में मैं कोड के साथ जारी रखने मैं इसे की कोशिश करेंगे, लेकिन अब के लिए, the_joric का जवाब मेरी तत्काल जरूरतों के लिए सबसे सीधा था। इनपुट के लिए धन्यवाद! – bigmac

1

आप एक छोटे इंटरफ़ेस पागल जा सकते हैं और निम्न करें:

using System; 
using System.Collections.Generic; 
using System.Linq; 

namespace ConsoleApplication3 
{ 

    public class MemberStatus : IDefault<MemberStatus> 
    { 
     public int StatusId { get; set; } 
     public string Name { get; set; } 

     public MemberStatus Default 
     { 
      get { return new MemberStatus() { StatusId = 0, Name = "All" }; } 
     } 

     public string IdName 
     { 
      get { return "StatusId"; } 
     } 
    } 

    public class MemberTeam : IDefault<MemberTeam> 
    { 
     public int TeamId { get; set; } 
     public string Name { get; set; } 

     public MemberTeam Default 
     { 
      get { return new MemberTeam() { TeamId = 0, Name = "All" }; } 
     } 

     public string IdName 
     { 
      get { return "TeamId"; } 
     } 
    } 

    public interface IDefault<T> 
    { 
     T Default { get; } 
     string IdName { get; } 
    } 

    public interface IRepository<T> 
    { 
     IEnumerable<T> All(); 
    } 

    public class MemberStatusRepository : IRepository<MemberStatus> 
    { 
     public IEnumerable<MemberStatus> All() 
     { 
      return new[] { 
       new MemberStatus(), 
       new MemberStatus() 
      }; 
     } 
    } 
    public class MemberTeamRepository : IRepository<MemberTeam> 
    { 
     public IEnumerable<MemberTeam> All() 
     { 
      return new[] { 
       new MemberTeam(), 
       new MemberTeam() 
      }; 
     } 
    } 

    public class DataAccessLayer 
    { 
     IRepository<MemberStatus> _memberStatusRepository; 
     IRepository<MemberTeam> _memberTeamRepository; 
     public DataAccessLayer() 
     { 
      _memberStatusRepository = new MemberStatusRepository(); 
      _memberTeamRepository = new MemberTeamRepository(); 
     } 


     public SelectList<TResult> GetTeamSelectList<TRepository, TResult>(TRepository repo, int selectedTeamId) 
      where TRepository : IRepository<TResult> 
      where TResult : IDefault<TResult>, new() 
     { 
      List<TResult> teamList = repo.All().ToList(); 
      var dummyobj = new TResult(); 
      teamList.Insert(0, dummyobj.Default); 
      var teamSelectList = new SelectList<TResult>(teamList, dummyobj.IdName, "Name", selectedTeamId); 
      return teamSelectList; 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var dal = new DataAccessLayer(); 
      SelectList<MemberStatus> results = dal.GetTeamSelectList<IRepository<MemberStatus>, MemberStatus>(new MemberStatusRepository(), 5); 
      Console.WriteLine(); 
      Console.Read(); 
     } 
    } 

    public class SelectList<TResult> 
    { 
     public SelectList(List<TResult> teamList, string p, string p_2, int selectedTeamId) 
     { 

     } 
    } 

} 

यह अच्छा होगा यदि आप एक अंतरफलक में स्थिर गुणों को परिभाषित सकता है, लेकिन जब से तुम मैं एक डमी वस्तु बनाने पर भरोसा नहीं कर सकते बजाय।

+0

@foson मदद करने में खुशी ... वाह! सभी कोड के लिए धन्यवाद। मैं देख सकता हूं कि आप कहां जा रहे हैं, और मुझे लगता है कि मैं अपनी पद्धति को अपनाने के लिए अपने डोमेन वर्ग के थोड़ा रिफैक्टरिंग करने पर काम कर सकता हूं, लेकिन अभी के लिए, मेरी तत्काल जरूरतों को पूरा करने के लिए_जोरिक का जवाब सबसे बुनियादी तरीका था, इसलिए मैं हूं इसे स्वीकार कर रहा हूँ लेकिन फिर, मैं आपका कोड एक संदर्भ के रूप में रख रहा हूं ताकि मैं निकट भविष्य में कुछ और भारी रिफैक्टरिंग पर काम कर सकूं, इसलिए आपके समय और विस्तार के लिए बहुत बहुत धन्यवाद! – bigmac

+0

एनपी। जैसे मैंने कहा, मेरा समाधान पागल थोड़ा सा इंटरफेस है - गतिशील उपयोग करने से निश्चित रूप से अधिक जटिल/कम पठनीय। यदि मैं गतिशील या प्रतिबिंब का उपयोग कर रहा था, तो व्यक्तिगत रूप से मुझे यह सुनिश्चित करने के लिए कुछ perf परीक्षण करना होगा कि समाधान मेरी स्वीकार्य perf अपेक्षाओं के भीतर है। – foson

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