c# - इंटरफ़ेस को लागू करने वाले सभी प्रकार प्राप्त करना




optimization reflection (8)

प्रतिबिंब का उपयोग करके, मैं कम से कम कोड के साथ सी # 3.0 / .NET 3.5 के साथ इंटरफेस को कार्यान्वित करने वाले सभी प्रकार कैसे प्राप्त कर सकता हूं, और पुनरावृत्तियों को कम कर सकता हूं?

यही वह है जिसे मैं फिर से लिखना चाहता हूं:

foreach (Type t in this.GetType().Assembly.GetTypes())
    if (t is IMyInterface)
        ; //do stuff

IFoo इंटरफ़ेस को लागू करने वाली असेंबली में सभी प्रकारों को ढूंढने के लिए:

var results = from type in someAssembly.GetTypes()
              where typeof(IFoo).IsAssignableFrom(type)
              select type;

ध्यान दें कि रयान रिनडीडी का सुझाव गलत था। यह 0 प्रकार वापस आ जाएगा। आप लिख नहीं सकते

where type is IFoo

क्योंकि प्रकार एक सिस्टम है। उदाहरण उदाहरण, और कभी भी IFoo प्रकार नहीं होगा। इसके बजाय, आप यह देखने के लिए जांचते हैं कि IFoo प्रकार से असाइन करने योग्य है या नहीं। इससे आपके अपेक्षित परिणाम मिलेंगे।

इसके अलावा, एडम राइट के सुझाव, जिसे वर्तमान में उत्तर के रूप में चिह्नित किया गया है, भी गलत है, और इसी कारण से। रनटाइम पर, आप देखेंगे कि 0 प्रकार वापस आते हैं, क्योंकि सभी सिस्टम। टाइप उदाहरण IFoo कार्यान्वयन नहीं थे।


आप जो करना चाहते हैं उसे करने के लिए कोई आसान तरीका नहीं है (प्रदर्शन के संदर्भ में)।

प्रतिबिंब असेंबली और प्रकारों के साथ मुख्य रूप से काम करता है, इसलिए आपको असेंबली के सभी प्रकार मिलना होगा और सही इंटरफेस के लिए उन्हें पूछना होगा। यहां एक उदाहरण दिया गया है:

Assembly asm = Assembly.Load("MyAssembly");
Type[] types = asm.GetTypes();
Type[] result = types.where(x => x.GetInterface("IMyInterface") != null);

यह आपको उन सभी प्रकारों को प्राप्त करेगा जो असेंबली माईएस्प्लिब्स में आईएमई इंटरफेस को लागू करते हैं


मुझे सराहना है कि यह एक बहुत पुराना सवाल है, लेकिन मैंने सोचा कि मैं भविष्य के उपयोगकर्ताओं के लिए एक और जवाब जोड़ूंगा क्योंकि तारीख के सभी उत्तर Assembly.GetTypes कुछ रूपों का उपयोग करते हैं। Assembly.GetTypes

जबकि GetTypes () वास्तव में सभी प्रकारों को वापस कर देगा, इसका मतलब यह नहीं है कि आप उन्हें सक्रिय कर सकते हैं और इस प्रकार संभावित रूप से एक ReflectionTypeLoadException टाइप टाइप लोड अपवाद कर सकते हैं।

एक प्रकार को सक्रिय करने में सक्षम नहीं होने के लिए एक क्लासिक उदाहरण तब होगा जब लौटाया गया प्रकार base से derived गया है लेकिन base को derived एक अलग असेंबली में परिभाषित किया गया है, एक असेंबली जो कॉलिंग असेंबली संदर्भित नहीं करती है।

तो कहें कि हमारे पास है:

Class A // in AssemblyA
Class B : Class A, IMyInterface // in AssemblyB
Class C // in AssemblyC which references AssemblyB but not AssemblyA

यदि ClassC जो AssemblyC तो हम स्वीकार किए गए उत्तर के अनुसार कुछ करते हैं:

var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(s => s.GetTypes())
    .Where(p => type.IsAssignableFrom(p));

फिर यह एक ReflectionTypeLoadException फेंक देगा।

ऐसा इसलिए है क्योंकि AssemblyA में AssemblyC संदर्भ के बिना आप निम्न में सक्षम नहीं होंगे:

var bType = typeof(ClassB);
var bClass = (ClassB)Activator.CreateInstance(bType);

दूसरे शब्दों में ClassB लोड करने योग्य नहीं है जो कुछ ऐसा है जो GetTypes को कॉल करता है और फेंकता है।

इसलिए लोड करने योग्य प्रकारों के लिए परिणाम सेट को सुरक्षित रूप से अर्हता प्राप्त करने के लिए, इस फिल हैकड आलेख के अनुसार एक असेंबली और जॉन स्कीट कोड में सभी प्रकार प्राप्त करें, आप इसके बजाय कुछ ऐसा करेंगे:

public static class TypeLoaderExtensions {
    public static IEnumerable<Type> GetLoadableTypes(this Assembly assembly) {
        if (assembly == null) throw new ArgumentNullException("assembly");
        try {
            return assembly.GetTypes();
        } catch (ReflectionTypeLoadException e) {
            return e.Types.Where(t => t != null);
        }
    }
}

और तब:

private IEnumerable<Type> GetTypesWithInterface(Assembly asm) {
    var it = typeof (IMyInterface);
    return asm.GetLoadableTypes().Where(it.IsAssignableFrom).ToList();
}

मेरा सी # 3.0 में होगा :)

var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(s => s.GetTypes())
    .Where(p => type.IsAssignableFrom(p));

असल में, कम से कम पुनरावृत्तियों की मात्रा हमेशा होगी:

loop assemblies  
 loop types  
  see if implemented.

यह मेरे लिए काम किया। यह कक्षाओं और जांच करता है कि वे मेरे इंटरफेस से वंचित हैं या नहीं

 foreach (Type mytype in System.Reflection.Assembly.GetExecutingAssembly().GetTypes()
                 .Where(mytype => mytype .GetInterfaces().Contains(typeof(myInterface)))) {
    //do stuff
 }

यहां अन्य उत्तर IsAssignableFrom का उपयोग IsAssignableFrom । जैसा कि here वर्णित है, आप System नेमस्पेस से FindInterfaces भी उपयोग कर सकते here

यहां एक उदाहरण दिया गया है जो वर्तमान में निष्पादित असेंबली के फ़ोल्डर में सभी असेंबली की जांच करता है, जो एक निश्चित इंटरफ़ेस को लागू करने वाले वर्गों की तलाश करता है (स्पष्टता के लिए LINQ से परहेज करता है)।

static void Main() {
    const string qualifiedInterfaceName = "Interfaces.IMyInterface";
    var interfaceFilter = new TypeFilter(InterfaceFilter);
    var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    var di = new DirectoryInfo(path);
    foreach (var file in di.GetFiles("*.dll")) {
        try {
            var nextAssembly = Assembly.ReflectionOnlyLoadFrom(file.FullName);
            foreach (var type in nextAssembly.GetTypes()) {
                var myInterfaces = type.FindInterfaces(interfaceFilter, qualifiedInterfaceName);
                if (myInterfaces.Length > 0) {
                    // This class implements the interface
                }
            }
        } catch (BadImageFormatException) {
            // Not a .net assembly  - ignore
        }
    }
}

public static bool InterfaceFilter(Type typeObj, Object criteriaObj) {
    return typeObj.ToString() == criteriaObj.ToString();
}

यदि आप एक से अधिक मिलान करना चाहते हैं तो आप इंटरफेस की एक सूची सेट अप कर सकते हैं।


सभी लोडेड असेंबली के माध्यम से लूप, अपने सभी प्रकार के माध्यम से पाश, और जांचें कि क्या वे इंटरफेस को लागू करते हैं।

कुछ इस तरह:

Type ti = typeof(IYourInterface);
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) {
    foreach (Type t in asm.GetTypes()) {
        if (ti.IsAssignableFrom(t)) {
            // here's your type in t
        }
    }
}

सूची पाने के लिए आप कुछ LINQ का उपयोग कर सकते हैं:

var types = from type in this.GetType().Assembly.GetTypes()
            where type is ISomeInterface
            select type;

लेकिन वास्तव में, क्या यह और अधिक पठनीय है?





c#-3.0