2010-07-08 7 views
7

से कैसे बच सकता हूं मेरे पास फॉलोइंग कोड है और मैं इसे इस तरह लिखना चाहूंगा कि मेरे पास कोड की न्यूनतम पंक्तियां हों और काम उसी तरह किया जाता है। मैं उसे कैसे कर सकता हूँ?मैं कोड डुप्लिकेशंस

List<Category> categoryList = new List<Category>(); 
categoryList = Category.LoadForProject(project.ID).ToList(); 
List<string> categories = new List<string>(Categories); 
IList<Category> currentCategories = Category.LoadForProject(project.ID).ToList(); 
if (currentCategories != null) 
{ 
    foreach (var existingCategories in currentCategories) 
    { 
     if (categories.Contains(existingCategories.Name)) 
      categories.Remove(existingCategories.Name); 
     else 
      existingCategories.Delete(Services.UserServices.User); 
    } 
    foreach (string item in categories) 
    { 
     Category category = new Category(project, item.ToString()); 
     category.Project = project; 
     category.Save(); 
    } 
} 

List<string> priorities = new List<string>(Priorities); 
IList<Priority> currentPriorities = Priority.LoadForProject(project.ID).ToList(); 
if (currentPriorities != null) 
{ 
    foreach (var existingPriorities in currentPriorities) 
    { 
     if (priorities.Contains(existingPriorities.Name)) 
      priorities.Remove(existingPriorities.Name); 
     else 
      existingPriorities.Delete(Services.UserServices.User); 
    } 
    foreach (string item in priorities) 
    { 
     Priority priority = new Priority(project, item.ToString()); 
     priority.Project = project; 
     priority.Save(); 
    } 
} 

उत्तर

9

कुछ इस तरह यह करना चाहिए:

public IList<T> DoYourThing<T>(IList<T> items, IList<T> currentItems, Project project) where T : CommonBaseType 
{ 
    if (currentItems != null) 
    { 
    foreach (var existingItem in currentItems) 
    { 
     if (items.Contains(existingItem.Name)) 
     items.Remove(existingItem.Name); 
     else 
     existingItems.Delete(Services.UserServices.User); 
    } 
    foreach (string item in items) 
    { 
     T newItem = Activator.CreateInstance(typeof(T), new object[] {project, item.ToString()}) as T; 
     newItem.Project = project; 
     newItem.Save(); 
    } 
    } 

    return currentItems; 
} 

तो फिर तुम इस तरह यह कॉल कर सकते हैं: अंत में

var currentCategories = DoYourThing(Categories.ToList(), Category.LoadForProject(project.ID).ToList()); 
var currentProjects = DoYourThing(Priorities.ToList(), Priority.LoadForProject(project.ID).ToList()); 

, तो आप विशेष रूप से दो बातों पर ध्यान देना चाहिए: सबसे पहले, एक सामान्य है फ़ंक्शन where T : CommonBaseType पर हालत। मुझे लगता है कि श्रेणी और प्रोजेक्ट में एक सामान्य आधार प्रकार या इंटरफ़ेस है जिसमें नाम शामिल है। यदि नहीं, तो आपको शर्त से छुटकारा पाना चाहिए और नाम पर जाने के लिए डायनामिक का उपयोग करना चाहिए।

दूसरा, मैं एक्टिवेटर का उपयोग कर रहा हूं। आपके लिए कक्षा बनाने के लिए तैयार करें। यह मुश्किल हिस्सा है जो इसे समझना मुश्किल बनाता है, अगर आपको यह पता नहीं चलता है कि

शुभकामनाएँ!

+0

जेनिक्स एक अच्छा समाधान है ... आपके कॉल को उस प्रकार को जोड़ने की आवश्यकता होगी, यानी 'var currentCategories = DoYourThing (श्रेणियाँ.ToList(), Category। लोडफोरप्रोजेक्ट (project.ID)। टोलीस्ट()) ; '? – Lazarus

+0

@ लासरस: नहीं। जब पैरामीटर द्वारा इस प्रकार का अनुमान लगाया जा सकता है (इस मामले में), विधि पर प्रकार की घोषणा अनावश्यक है। :) –

+0

@ ब्रायन जेनिसियो आपका अधिकार है कि अगर आप एक्टिवेटर को समझ नहीं पाते हैं तो असंभव रूप से आना मुश्किल है। भाग लें। यह सरल जीनियस है। – msarchet

7

मेक प्राथमिकता और श्रेणी एक ही इंटरफ़ेस लागू करने या उस में सामान्य गुणों (अर्थात .Project, .Name और .save) के साथ एक वर्ग से निकाले जाते हैं। फिर उस इंटरफ़ेस या बेस क्लास का उपयोग अपने फ़ंक्शन के प्रकार के रूप में करें और आप दोनों कक्षाओं के संग्रह को पारित करने में सक्षम होंगे।

+0

मुझे यह मारो ... कुछ कोड के बारे में ... – Lazarus

+0

@ लाज़र आधा रास्ते था, हालांकि मैंने देखा कि @ ब्रायन जेनिसियो ने इस बिंदु को अच्छी तरह से चित्रित किया है! – w69rdy

0

यदि Priority और Category दोनों या तो समान आधार वर्ग से विधि/गुणों के एक सामान्य सेट के साथ व्युत्पन्न होते हैं, या उसी इंटरफ़ेस को लागू करते हैं तो हाँ, आप कर सकते हैं। आपको केवल बेस क्लास या इंटरफ़ेस (लागू होने पर) के संदर्भ के साथ विशिष्ट संदर्भों को Priority और Category पर प्रतिस्थापित करने की आवश्यकता होगी।

कुछ मामूली कोड मतभेद हैं (जैसे कि पहले कोड ब्लॉक में List<string>(Categories)) कि आपको संभालने के बारे में सोचना होगा, लेकिन अधिकांश कोड पूर्वजों/इंटरफ़ेस प्रश्न के निपटारे के बाद ही स्थानांतरित हो जाएंगे।

+0

मुझे नहीं लगता कि यह विरासत के लिए एक मामला है क्योंकि वर्ग पदानुक्रम समझ में नहीं आता है। आप एक मनमाना आधार वर्ग बना सकते हैं लेकिन यह बाल वर्गों के लिए एक आम पूर्वज होने की भावना का पालन नहीं करेगा। एक इंटरफेस अलग वर्गों के लिए एक आम 'एपीआई' प्रदान करने के लिए यहां और अधिक समझ में आता है। – Lazarus

0

मुझे dynamic समान गुणों का पर्दाफाश करने वाले प्रकारों के सेट के लिए बहुत उपयोगी लगता है, लेकिन एक ही इंटरफ़ेस को लागू नहीं करते हैं।

foreach(dynamic d in myList)... d.Name... के साथ सूची के माध्यम से Iterate, इसे एक विधि में लपेटें, और विभिन्न IList<object> उदाहरण (श्रेणियां या प्राथमिकताएं) पास करें।

सी # 4.0 की आवश्यकता है।

+1

यह सिर्फ मुझे धोखा देने जैसा लगता है ;-) –

+0

जौके जैसा ही है। यह सिर्फ आलसी है। गतिशील का इरादा नहीं है कि आपको इंटरफेस को परिभाषित करने की आवश्यकता नहीं है। – cRichter

+0

धन्यवाद, उत्तर देने के लिए बहुत कुछ। मैं सी # के लिए नया हूँ। क्या आप मुझे गतिशील का उपयोग कर कोड का टुकड़ा दे सकते हैं। धन्यवाद – learning

0

आप प्राथमिकता और श्रेणी एक ही आधार वर्ग से निकाले जाते हैं बनाने की जरूरत है ... और फिर आप की तर्ज पर कुछ कर सकते हैं:

public void ProcessLists<ItemType>(Func<int, IEnumerable<ItemType>> Loader) whereItemType : CommonBase, new() { 
List<string> items = new List<string>(); 
IList<ItemType> currentItems = Loader(project.ID).ToList(); 
if (currentItems != null) { 
    foreach (var existingItem in currentItems) { 
     if (items.Contains(existingItem.Name)) 
      items.Remove(existingItem.Name); 
     else 
      existingItem.Delete(Services.UserServices.User); 
    } 
    foreach (string item in items) { 
     ItemType item = new ItemType(); 
     item.Project = project 
     item.Name = item.ToString(); 
     item.Save(); 
    } 
} 

}

बेशक

, कुछ प्रकार (जैसे प्रोजेक्ट.आईडी के रूप में) केवल अनुमान लगाया जाता है और उचित लाइनों के साथ प्रतिस्थापित किया जाना चाहिए।

आप इस तरह से प्राथमिकता के लिए फ़ंक्शन को कॉल कर सकते हैं:

ProcessLists<Priority>(id => Priority.LoadForProject(project.ID)); 
+0

इस समाधान के साथ, जब आप नए आइटम टाइप को कॉल करने की आवश्यकता होती है, तो आप अटक जाते हैं, क्योंकि इसे वास्तविक प्रकार के आधार पर अलग होना चाहिए। जेनेरिक यहां जाने का रास्ता हैं। –

+0

@ ब्रायन: हम्म, मुझे डर है कि मैं तुम्हारा बिंदु नहीं देखता हूं। क्या आप इसे और समझा सकते हैं? – Christian

+0

@ क्रिस्टियन: अपने दो अलग-अलग कार्यान्वयन में, उन्होंने नई श्रेणी (तर्क) और नई परियोजना (तर्क) को बुलाया। आप केवल नए आइटम टाइप() को कॉल नहीं कर सकते हैं। आपको जिस प्रकार की उम्मीद है वह आपको नहीं मिलेगा। आपको विधि जेनेरिक बनाने की आवश्यकता है, और एक्टिवेटर को कॉल करने की आवश्यकता है। ItemType का सही व्युत्पन्न बनाने के लिए बनाएं (टाइपोफ (टी), तर्क)। –

1

ठीक है, जहाँ तक मैं समझ गया, तो आप 'नई' सूची की श्रेणियों/प्राथमिकताओं जोड़ना चाहते हैं, विद्यमान नहीं कर रहे हैं कि भंडार में।

इसे बनाते हैं।

public void SaveNewItems<T>(IList<string> newList, IList<T> currentList, string project) 
    where T: new(), IStoreableItem 
{ 
    //find only new items 
    var toAdd = from itemName in newList 
       where !currentList.Contains(i => i.Name = itemName) 
       select new T { 
        Name = itemName, 
        Project = project 
       }; 


    //find items to delete 
    var toDelete = from item in currentList 
        where !newList.Contains(item.Name) 
        select item; 

    toAdd.ToList().ForEach(item => item.Save()); 
    toDelete.ToList().ForEach(item => item.Delete()); 
} 

श्रेणी और प्रिय ISToreableItem से प्राप्त होना चाहिए जिसमें नाम, प्रोजेक्ट, और सहेजें/हटाएं विधि शामिल है।

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