2009-07-13 18 views
51

लागू करता है मान लें कि मेरे पास एक प्रकार है, MyType। मैं निम्न कार्य करना चाहते हैं:यह पता लगाना कि कोई प्रकार एक सामान्य इंटरफ़ेस

  1. पता करें कि MyType IList इंटरफ़ेस लागू करता है, कुछ टी
  2. के लिए तो का जवाब (1) है हाँ, यह पता लगाने क्या टी है।

ऐसा लगता है कि यह GetInterface() है, लेकिन यह केवल आपको एक विशिष्ट नाम से खोज करने देता है। वहाँ के लिए "सभी इंटरफ़ेस उस रूप IList के हैं" खोज करने के लिए एक रास्ता है

संबंधित (यदि संभव हो तो यह भी उपयोगी है अगर यह काम करता है, तो इंटरफ़ेस IList की एक subinterface था woudl।): How to determine if a type implements a specific generic interface type

उत्तर

80
// this conditional is necessary if myType can be an interface, 
// because an interface doesn't implement itself: for example, 
// typeof (IList<int>).GetInterfaces() does not contain IList<int>! 
if (myType.IsInterface && myType.IsGenericType && 
    myType.GetGenericTypeDefinition() == typeof (IList<>)) 
    return myType.GetGenericArguments()[0] ; 

foreach (var i in myType.GetInterfaces()) 
    if (i.IsGenericType && i.GetGenericTypeDefinition() == typeof (IList<>)) 
     return i.GetGenericArguments()[0] ; 

संपादित करें: myType लागू करता यहां तक ​​कि अगर IDerivedFromList<> नहीं बल्कि सीधे IList<>, IList<> होगा सरणी में दिखाएं GetInterfaces() द्वारा लौटाया गया।

अद्यतन: किनारे के मामले के लिए एक चेक जोड़ा गया जहां myType प्रश्न में सामान्य इंटरफ़ेस है।

+0

यह सरणी के मामले को भी संभालता है, जो अच्छा है। यदि आप स्पष्ट रूप से सरणी के लिए परीक्षण करना चाहते हैं तो "if (myType.IsArray) का उपयोग करें MyType.GetElementType();" (और यह तेजी से हो सकता है, मुझे आशा है कि इनमें से कोई भी प्रदर्शन-महत्वपूर्ण नहीं है!) – yoyo

+0

मेरे जैसे लोगों के लिए जो उत्सुक थे कि ISInterface की आवश्यकता क्यों है: GetGenericTypeDefinition() को गैर-सामान्य प्रकार पर बुलाया जाता है। – GameFreak

+0

Type.IsGenericType संपत्ति netstandard 1.6 और निम्न (और इस प्रकार .NET कोर 1.0 पर उपलब्ध नहीं है) पर उपलब्ध नहीं है, लेकिन आप इसके बजाय TypeInfo.IsGenericType का उपयोग कर सकते हैं: type.GetTypeInfo()। IsGenericType। – dotarj

0

हैं मैं आपके प्रश्न को सही ढंग से समझता हूं, यही वह है जो आप करने की कोशिश कर रहे हैं। यदि नहीं, तो कृपया आगे बताएं।

public class MyType : ISomeInterface 
{ 
} 

MyType o = new MyType(); 

if(o is ISomeInterface) 
{ 
} 

संपादित करें: अगर आप अपने प्रश्नों को बदलने के लिए, कृपया तथ्य यह है कि आप अब edited..because मेरा उत्तर ऐसा लगता है कि संबंधित नहीं है जोड़ें।

उस मामले में, यहाँ एक बहुत बड़ी LINQ

  var item = typeof(MyType).GetInterfaces() 
          .Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IList<>)) 
          .Select(t => t.GetGenericArguments().First()) 
          .FirstOrDefault(); 

if(item != null) 
//it has a type 
11

आसानी से प्रतिबिंब का उपयोग करना (और कुछ LINQ) आप कर सकते हैं ऐसा करते हैं:

public static IEnumerable<Type> GetIListTypeParameters(Type type) 
{ 
    // Query. 
    return 
     from interfaceType in type.GetInterfaces() 
     where interfaceType.IsGenericType 
     let baseInterface = interfaceType.GetGenericTypeDefinition() 
     where baseInterface == typeof(IList<>) 
     select interfaceType.GetGenericArguments().First(); 
} 

सबसे पहले, आप प्रकार पर इंटरफेस हो रही है और केवल उन है कि एक सामान्य प्रकार के होते हैं के लिए को छान रहे हैं।

फिर, आपको उन इंटरफ़ेस प्रकारों के लिए सामान्य प्रकार की परिभाषा मिलती है, और देखें कि यह IList<> जैसा ही है।

वहां से, मूल इंटरफ़ेस के लिए सामान्य तर्क प्राप्त करने का यह एक साधारण मामला है।

याद रखें, एक प्रकार में कई IList<T> कार्यान्वयन हो सकते हैं, यही कारण है कि IEnumerable<Type> वापस आ गया है।

+0

यदि आप रिटर्न एक्सप्रेशन को ब्रांड्स में लपेटते हैं और अंत में एक और "फर्स्ट()" जोड़ते हैं तो यह लंबाई -1 के बजाय एक प्रकार देता है INumerable , जो इससे निपटने के लिए थोड़ा आसान है। (व्यक्तिगत रूप से मुझे लगता है कि यह LINQ के साथ बहुत चालाक होने का एक उदाहरण है, लेकिन हो सकता है कि यह सिर्फ मुझे है।) – yoyo

+0

@ योयो या, आप इस विधि के परिणामों पर केवल 'फर्स्ट' को कॉल कर सकते हैं। यदि आप इस विधि से 'फर्स्ट' वापस करते हैं, तो आप * एक प्रकार पैरामीटर मानते हैं जो सीधे * गलत * है। – casperOne

+0

अच्छा बिंदु @ कैस्परऑन, ओपी का माईटाइप IList और IList लागू कर सकता है। तो सवाल यह होना चाहिए कि "टी ढूंढें" नहीं "टी ढूंढें"। स्वीकृत उत्तर इस से निपटता नहीं है। – yoyo

1

एक सहायक विधि विस्तार के रूप में

public static bool Implements<I>(this Type type, I @interface) where I : class 
{ 
    if(((@interface as Type)==null) || !(@interface as Type).IsInterface) 
     throw new ArgumentException("Only interfaces can be 'implemented'."); 

    return (@interface as Type).IsAssignableFrom(type); 
} 

उदाहरण उपयोग:

var testObject = new Dictionary<int, object>(); 
result = testObject.GetType().Implements(typeof(IDictionary<int, object>)); // true! 
4
public static bool Implements<I>(this Type type) where I : class 
    { 
     if (!typeof(I).IsInterface) 
     { 
      throw new ArgumentException("Only interfaces can be 'implemented'."); 
     } 

     return typeof(I).IsAssignableFrom(type); 
    } 
1

एंटोन Tykhyy के प्रस्ताव का उपयोग करते हुए, यहाँ कुछ प्रकार के साथ एक सामान्य इंटरफ़ेस लागू करता है, तो जाँच करने के लिए एक छोटा सा विस्तार विधि है एक सामान्य प्रकार के पैरामीटर दिए गए:

public static class ExtensionMethods 
{ 
    /// <summary> 
    /// Checks if a type has a generic interface. 
    /// For example 
    ///  mytype.HasGenericInterface(typeof(IList<>), typeof(int)) 
    /// will return TRUE if mytype implements IList<int> 
    /// </summary> 
    public static bool HasGenericInterface(this Type type, Type interf, Type typeparameter) 
    { 
     foreach (Type i in type.GetInterfaces()) 
      if (i.IsGenericType && i.GetGenericTypeDefinition() == interf) 
       if (i.GetGenericArguments()[0] == typeparameter) 
        return true; 

     return false; 
    } 
} 
संबंधित मुद्दे