2012-04-27 8 views
11

इस विषय के बारे में बहुत सारे प्रश्न हैं, लेकिन मेरे पास इसका थोड़ा सा संस्करण है।निर्धारित करें कि कोई वर्ग एक बहुत ही विशिष्ट इंटरफ़ेस लागू करता है

interface IFoo { } 
interface IBar : IFoo { } 
class Foo : IFoo { } 
class Bar : IBar { } 

bool Implements_IFoo(Type type) { /* ??? */ } 

अब, कहानी का मोड़: विधि Implements_IFoo ही सच्चा लौट जाना चाहिए जब प्रकार IFoo केवल और नहीं लागू करता है इंटरफेस IFoo से व्युत्पन्न के किसी भी

हम निम्नलिखित कोड है।

Implements_IFoo(typeof(Foo)); // Should return true 

Implements_IFoo(typeof(Bar)); // Should return false as Bar type 
           // implements an interface derived from IFoo 

ध्यान दें कि वहाँ IFoo से प्राप्त कई इंटरफेस हो सकता है और आप जरूरी अपने अस्तित्व के बारे में पता नहीं है: यहाँ इसे समझने के लिए इस विधि के कुछ उदाहरण हैं।

स्पष्ट विधि है IFoo से प्रतिबिंबित सभी इंटरफ़ेस को प्रतिबिंब के माध्यम से प्राप्त करना और फिर टाइपफ़ोफ़ (बार) की जांच करें। गेटइंटरफेस() उनमें से कोई भी मौजूद है। लेकिन मैं सोच रहा था कि कोई और अधिक सुरुचिपूर्ण समाधान के साथ आ सकता है।

पीएस प्रश्न कुछ कोड से निकला है जो मैंने पाया है कि कक्षाओं पर इस चेक का उपयोग करता है (if(obj.GetType() == typeof(BaseClass)) { ... })। हम अब विशेष कोड के साथ कक्षाओं को इंटरफेस के साथ बदल रहे हैं। इसके अलावा, बस मामले में - मैं इस चेक को बुलियन ध्वज के रूप में कार्यान्वित कर रहा हूं, इसलिए यह प्रश्न पूरी तरह से काल्पनिक है।

+1

मैं वास्तव में उत्सुक हूं कि आपको इस तरह के आत्मनिरीक्षण की आवश्यकता क्यों है। संभावना है कि आपका डिजाइन गलत है। – tdammers

+0

कृपया अगली बार टिप्पणी करने से पहले अंत तक प्रश्न पढ़ें - मैंने पहले ही समझाया है कि यह एक काल्पनिक प्रश्न है;) – Jefim

उत्तर

9

मैं क्योंकि यह मज़ा की तरह लग रहा एक कोशिश थी, और यह आपके उदाहरण के लिए काम करता है:

bool ImplementsIFooDirectly(Type t) { 
    if (t.BaseType != null && ImplementsIFooDirectly(t.BaseType)) { 
     return false; 
    } 
    foreach (var intf in t.GetInterfaces()) { 
     if (ImplementsIFooDirectly(intf)) { 
      return false; 
     } 
    } 
    return t.GetInterfaces().Any(i => i == typeof(IFoo)); 
} 

परिणाम:

ImplementsIFooDirectly(typeof(IFoo)); // false 
ImplementsIFooDirectly(typeof(Bar)); // false 
ImplementsIFooDirectly(typeof(Foo)); // true 
ImplementsIFooDirectly(typeof(IBar)); // true 

यह से ली गई सभी इंटरफेस के लिए नहीं लगती है IFoo, यह सिर्फ विरासत/इंटरफेस कार्यान्वयन श्रृंखला की यात्रा करता है और देखता है कि IFoo इस प्रकार के सटीक स्तर के अलावा किसी भी स्तर पर मौजूद है या नहीं।

यह भी पता लगाता है कि इंटरफ़ेस को बेस प्रकार के माध्यम से विरासत में मिला है या नहीं। सुनिश्चित नहीं है कि आप यही चाहते हैं।

फिर भी, जैसा कि अन्य ने पहले ही कहा है, अगर यह वास्तव में आपके लिए एक आवश्यकता है, तो आपको अपने डिजाइन में कोई समस्या हो सकती है। (संपादित करें: बस देखा है कि आपका सवाल है विशुद्ध रूप से काल्पनिक तो यह निश्चित रूप से ठीक है :)।)

+0

धन्यवाद, यही मेरा मतलब है। अपने उत्तर को सही के रूप में चिह्नित करना क्योंकि यह पहला सही था। :) – Jefim

0

क्या आपने कीवर्ड is का उपयोग करने का प्रयास किया था?

सामान्य रूप से बीटीडब्ल्यू, यदि आपके पास एक तार्किक मामला है जहां कुछ वर्ग को कुछ बेस क्लास के प्रकार की आवश्यकता होती है लेकिन विरासत में से कोई भी नहीं है, तो शायद यह गलत ओओ डिज़ाइन है, जो Liskov substitution principle का उल्लंघन कर सकता है।

+1

'टाइप' ऑब्जेक्ट पर? – mellamokb

+0

फिर, 'is' मदद नहीं कर रहा है क्योंकि यह expr के लिए' true' वापस कर देगा। 'बार आईफू' है (और वांछित आउटपुट 'झूठा' है क्योंकि बार आईफार के माध्यम से आईफू लागू करता है)। और यदि आप पूरी तरह से प्रश्न को पढ़ने की परवाह करते हैं तो आपको लिस्कोव और ओओ डिज़ाइन का उल्लेख करने की आवश्यकता नहीं होगी। कीवर्ड: काल्पनिक/सैद्धांतिक। ;) – Jefim

3

उदाहरण के लिए निम्नलिखित साइट देखें कि इसे कैसे कार्यान्वित किया जा सकता है;

C# is keyword usage

अनिवार्य रूप से आप यह निर्धारित करने वस्तु यह वर्ग विरासत ढेर के हिस्से के रूप में एक वर्ग के प्रकार रहता है कि क्या 'है' कीवर्ड का उपयोग कर सकते हैं।

class Director : Owner { } 
class Developer : Employee { } 
.. 
var dave = new Developer(); 
var steve = new Director(); 
var isEmployee = dave is Employee; // true 
var isAlsoEmploye = steve is Employee; // false 
अपने उदाहरण समारोह के साथ

लाइन में:

bool Implements_Type(object instance, Type type) { 
return instance is type; 
} 
+0

मुझे 'है' कीवर्ड पता है और यह समस्या का समाधान नहीं करता है। उदाहरण के साथ कृपया मेरे प्रश्न का हिस्सा देखें। ध्यान दें कि आईबार आईफू से लिया गया है। इस प्रकार बार भी इसे इबार के माध्यम से लागू करता है। एक्सपीआर के लिए सच है 'बार आईफू' है लेकिन यह वांछित परिणाम नहीं है। – Jefim

0

प्रकार वर्ग एक विधि GetInterface कहा जाता है का उपयोग कर सकते है।

bool Implements_IFoo(Type t) 
    { 
     return t.GetInterface(typeof(IFoo).Name) != null; 
    } 
+0

जो पूरे पदानुक्रम में सभी इंटरफेस की जांच करता है, और इसलिए दूसरे उपयोग के मामले में विफल रहता है 'Implements_IFoo (टाइपऑफ (बार)); ' – mellamokb

2
static bool Implements_IFoo(Type type) 
{ 
    if (typeof(IFoo).IsAssignableFrom(type.BaseType)) 
    return false; 

    var barInterfaces = type.GetInterfaces() 
    .Where(iface => typeof(IFoo).IsAssignableFrom(iface)) 
    .ToArray(); 

    return barInterfaces.Length > 0 
    && barInterfaces.Length == barInterfaces.Count(iface => iface == typeof(IFoo)); 
} 
static bool Implements_IFoo_Optimized(Type type) 
{ 
    if (typeof(IFoo).IsAssignableFrom(type.BaseType)) 
    return false; 

    return type.GetInterfaces() 
    .Where(iface => typeof(IFoo).IsAssignableFrom(iface)) 
    .Count() == 1; 
} 
+0

उत्तर के लिए धन्यवाद! यह वही है जो मेरा मतलब था। – Jefim

1

इस चाल करना चाहिए:

public bool ImplementsIFooOnly(Type type) 
{ 
    return !type.GetInterfaces().Any(t => 
       { 
        return t is IFoo && !t.Equals(typeof(IFoo)); 
       }); 
} 

शायद और अधिक कुशल तरीके से कर रहे हैं।

+0

मुझे लगता है कि आपका मतलब है 'टाइपऑफ (आईएफयू)। आईएसएसिग्नेबल फ्रॉम (टी)' टी के बजाय आईएफयू है, लेकिन हाँ, यह सामान है :) – Jefim

+0

और बस मामले में - वह कोड आधार वर्गों की जांच नहीं करता है (ठीक है, मेरे प्रश्न में स्पष्ट रूप से परिभाषित नहीं किया गया था) और स्थिति जब किसी प्रकार के पास कोई इंटरफेस नहीं होता है (=> '.अन्य (..) 'फिर झूठी रिटर्न)। – Jefim

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