2011-12-06 27 views
6

युक्त रीफैक्टरिंग विधि में मुझे एक विधि को दोबारा करने का सबसे अच्छा तरीका तय करना है जिसमें LINQ क्वेरी शामिल हैं जो बहुत समान हैं लेकिन समान नहीं हैं।LINQ क्वेरी

एक तरीका है जिसके इन पंक्तियों के साथ कुछ है पर विचार करें: सिर्फ एक उदाहरण

public SomeObject GetTheObject(IMyObject genericObject) { 
    Type t = genericObject.GetType(); 
    SomeObject so = null; 

    switch(t.Name) { 
     case "Type1": 
      var object1 = (from o in object1s where o.object1id == genericObject.id).FirstOrDefault(); 
      so = (SomeObject)object1; 
     break; 
     case "Type2": 
      var object2 = (from o in object2s where o.object2id == genericObject.id).FirstOrDefault(); 
      so = (SomeObject)object2; 
     break; 
     default: 
     break; 
    } 

    return so; 
} 

यह वह जगह है, लेकिन कल्पना मैं एक अलग क्वेरी (यह एक अलग ObjectSet का उपयोग करता है में अलग निष्पादित करने के लिए की आवश्यकता होगी, कर रहा हूँ, थोड़ा का उपयोग करता है विभिन्न फ़ील्ड (object1id बनाम object2id) और एक अलग प्रकार देता है। इसके अलावा, प्रश्न समान हैं।

क्या इस तरह की विधि को दोबारा करने का कोई समझदार तरीका है? ऐसा लगता है जैसे मैंने कुछ स्पष्ट याद किया है। शायद मुझे सटीक विधि का उपयोग करना होगा और मैं क्वेरी को दोबारा लिखने से नहीं बच सकता, यह सिर्फ से है मुझे पसंद है जैसे किसी भी तरह से सक्षम होना चाहिए!

किसी भी संकेत दिए गए बहुत सराहना

+0

मैं प्रतिबिंब के साथ यह कोशिश की, लेकिन अतीत LINQ बयान नहीं मिल सका ("ओ ऑब्जेक्ट 1 में जहां o.object1id")। आपको गतिशील रूप से LINQ कथन उत्पन्न करना चाहिए। – Graham

+0

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

उत्तर

4

शायद तुम सिर्फ अपने परिदृश्य oversimplified है, लेकिन अपने कार्य की बदबूदार हिस्सा SomeObject के कलाकार हैं। क्या आप सिर्फ इंटरफेस के साथ काम नहीं कर सकते थे और (यदि आवश्यक हो) कॉल साइट पर परिणाम डाला? आप अपना टाइप 1 और टाइप 2 एक सामान्य इंटरफेस को कार्यान्वित कर सकते हैं जहां आईडी 1 और आईडी 2 आईडी के रूप में उजागर होते हैं, उदाहरण के लिए (या अगर आप टाइप 1 और टाइप 2 को नियंत्रित नहीं करते हैं तो उन्हें सजाने के लिए)

आईई।

public static IMyObject GetTheObject(List<IMyObject> theList, int id) 
{ 
    var ret = (from o in theList 
     where o.id==id 
     select o).FirstOrDefault(); 

    return ret; 
} 
उदाहरण के लिए

, यदि आपके पास:

public interface IMyObject {int id {get;}} 

    public class Foo : IMyObject {public int id {get; set;}} 
    public class Bar : IMyObject {public int id {get; set;}} 

आप कर सकते हैं:

var l1 = new List<IMyObject>(){new Foo(){id=1}, new Foo(){id=2}}; 
var l2 = new List<IMyObject>(){new Bar(){id=1}, new Bar(){id=2}}; 

var obj1 = Test.GetTheObject(l1, 1); 
var obj2 = Test.GetTheObject(l2, 2); 

और वस्तुओं डाली के बाद आप फ़ंक्शन को कॉल करें, यदि आप करने के लिए है।

संपादित करें: अगर आप ठोस वस्तुओं और डाले के साथ फंस रहे हैं, सबसे अच्छा रिफैक्टरिंग मैं के साथ आ सकता है:

public static SomeObject GetTheObject(IMyObject genericObject) { 
    Type t = genericObject.GetType(); 

    Func<SomeObject, bool> WhereClause = null; 
    IEnumerable<SomeObject> objs = null; // IEnumerable<T> is covariant, 
         // so we can assign it both an IEnumerable<object1> 
         // and an IEnumerable<object2> (provided object1 and 2 are 
         // subclasses of SomeObject) 

    switch(t.Name) { 
     case "Type1": 
      WhereClause = o => ((Object1)o).object1id == genericObject.id;  
      objs = object1s; 
     break; 
     case "Type2": 
      WhereClause = o => ((Object2)o).object2id == genericObject.id;  
      objs = object2s; 
     break; 
    } 

    var ob = objs 
    .Where(WhereClause) 
    .FirstOrDefault(); 

    return (SomeObject)ob; 
} 
+0

हाँ मुझे लगता है कि मैंने चीजों को थोड़ा सा सरल बना दिया है, मेरे पास इंटरफेस के साथ काम करने के साथ समस्या यह है कि मेरी क्वेरी वास्तव में एक सामान्य भंडार पर एक प्रश्न है जिसके लिए एक ठोस प्रकार की आवश्यकता होती है। इसका मतलब है कि मैं उस समय रेस्पोजिटरी नहीं कर सकता जो मुझे दुःख पैदा कर रहा है। मुझे लगता है कि मैं एक और भंडार लिख सकता हूं जहां टी: IMyObject, टी के बजाय, EntityObject यह फिलहाल है, लेकिन यह ओवरकिल की तरह लगता है, हालांकि इसकी आवश्यकता हो सकती है। – dougajmcdonald

+0

@dougajmcdonald: मैं जिस रिफैक्टरिंग के साथ आ सकता हूं वह आपके ऊपर सुधार की तरह नहीं दिखता है, लेकिन कम से कम यह लिनक कोड में डुप्लिकेशंस को कम करता है ... :) –

+0

इसके लिए धन्यवाद, जब मुझे मिलता है तो मेरे पास एक खेल होगा गुरुवार को एक मौका, मैं अपने वास्तविक जीवन की स्थिति में स्विचिंग तर्क से दूर जाने की उम्मीद कर रहा था, मेरे पास 10-12 विकल्प हो सकते हैं और मैं केस स्टेटमेंट के साथ स्क्रीन को नहीं उठाऊंगा!तो फिर यह एकमात्र विकल्प हो सकता है! – dougajmcdonald