प्रतिबिंब के माध्यम से एक नामस्थान में सभी प्रकार प्राप्त करना


268

सी # में प्रतिबिंब के माध्यम से एक नामस्थान में सभी कक्षाएं कैसे मिलती हैं?


क्या आप अपना प्रश्न संपादित कर सकते हैं ... सबटेक्स्ट प्रश्न '# Namespace in C #' से अधिक संप्रेषणीय है
Gishu

आप यहां देख सकते हैं । 2 अलग-अलग नमूने हैं।
फातिह गुरदयाल

जवाबों:


316

namespaceवर्तमान विधानसभा में निर्दिष्ट कोड में वर्गों के नाम निम्नलिखित हैं ।
जैसा कि अन्य लोगों ने बताया है, एक नेमस्पेस अलग-अलग मॉड्यूलों के बीच बिखर सकता है, इसलिए आपको पहले असेंबली की एक सूची प्राप्त करने की आवश्यकता है।

string nspace = "...";

var q = from t in Assembly.GetExecutingAssembly().GetTypes()
        where t.IsClass && t.Namespace == nspace
        select t;
q.ToList().ForEach(t => Console.WriteLine(t.Name));

83

जैसा कि फ्लाईस्वाट कहता है, आपके पास कई असेंबली (उदाहरण के लिए System.Collections.Generic) में एक ही नाम स्थान हो सकता है । यदि आप पहले से लोड नहीं हैं, तो आपको उन सभी विधानसभाओं को लोड करना होगा। तो एक पूर्ण उत्तर के लिए:

AppDomain.CurrentDomain.GetAssemblies()
                       .SelectMany(t => t.GetTypes())
                       .Where(t => t.IsClass && t.Namespace == @namespace)

यह तब तक काम करना चाहिए जब तक आप अन्य डोमेन की कक्षाएं नहीं चाहते। सभी डोमेन की सूची प्राप्त करने के लिए, इस लिंक का अनुसरण करें।


1
ठीक काम करता है - एक छोटा सा रिमाइंडर: मैंने " && t.Namespace == @namespace" हटाने की कोशिश की - "कौन सा टोकना मुझे सब कुछ देता है। नेट असेंबलियाँ :-)
Netsi1964

@ Netsi1964 अगर आप को दूर && t.Namespace == @namespaceतुम सब मिल कक्षाओं की सभी विधानसभाओं .net का भी शामिल है। GetAssembliesआप सभी विधानसभाओं GetAssemblies().SelectMany(t => t.GetTypes())को दे देंगे , और सभी विधानसभाओं से सभी प्रकार (कक्षाएं, संरचना आदि) दे देंगे।
नवफाल

मैंने डॉटनेट कोर 2.2 (2.1 से) में अपग्रेड किया और इस कोड ने मेरी विशिष्ट असेंबली के लिए काम करना बंद कर दिया। जिस असेंबली को मैं चाहता था उसे कोड में कहीं भी संदर्भित नहीं किया गया था, इसलिए लोड नहीं किया गया था! 2.1 में इसे लोड किया गया था, लेकिन लगता है कि 2.2 में लोडिंग है?
हार्वे

@ हाईवे क्या .NET कोर के साथ शुरू करने के लिए उपयुक्त है?
नवाफाल

@nawfal हाँ। यह कोड पहले 2.1 में काम करता था। मैंने पाया कि मैं Assembly.Load(nameof(NameOfMyNamespace))ठीक काम करके असेंबली को लोड करने के लिए मजबूर करता हूं ।
हार्वे

28
using System.Reflection;
using System.Collections.Generic;
//...

static List<string> GetClasses(string nameSpace)
{
    Assembly asm = Assembly.GetExecutingAssembly();

    List<string> namespacelist = new List<string>();
    List<string> classlist = new List<string>();

    foreach (Type type in asm.GetTypes())
    {
        if (type.Namespace == nameSpace)
            namespacelist.Add(type.Name);
    }

    foreach (string classname in namespacelist)
        classlist.Add(classname);

    return classlist;
}

NB: उपरोक्त कोड दिखाता है कि क्या हो रहा है। क्या आप इसे लागू करते हैं, एक सरलीकृत संस्करण का उपयोग किया जा सकता है:

using System.Linq;
using System.Reflection;
using System.Collections.Generic;
//...

static IEnumerable<string> GetClasses(string nameSpace)
{
    Assembly asm = Assembly.GetExecutingAssembly();
    return asm.GetTypes()
        .Where(type => type.Namespace == nameSpace)
        .Select(type => type.Name);
}

9
मैं मतलबी होने की कोशिश नहीं कर रहा हूं, लेकिन इस कोड में सभी मिली वस्तुओं के माध्यम से एक पूरी तरह से अनावश्यक सूची और चलना है; "नेमपैलिस्ट" के माध्यम से "क्लास लिस्ट" वेरिएबल और फॉर्च्यूनर "नेमपेसलिस्ट" को लौटने से अलग कोई कार्यक्षमता प्रदान नहीं करता है
TheXenocide

10
एक कोड नमूने की @TheXenocide उद्देश्य हमेशा लिखने कोड के लिए "सर्वश्रेष्ठ" रास्ता दिखाने के लिए नहीं है, लेकिन करने के लिए स्पष्ट रूप से व्यक्त कैसे कुछ किया जाता है।
रयान फार्ले

4
मैं सिर्फ शिक्षा के लिए इसे इंगित कर रहा था; यह हमारी ज़िम्मेदारी है कि हम उन लोगों को सर्वोत्तम उदाहरण से सीखें जिन्हें हम एक बुरे उदाहरण को उजागर करने के बजाय समझदारी को नकारात्मक रूप से प्रभावित करते हैं। मैं यह विशेष रूप से हानिकारक नहीं कह रहा हूं, लेकिन मैं भावुकता से असहमत हूं
TheXenocide

4
यदि मैं पूछे गए प्रश्न के लिए मददगार नहीं है, तो मैं नीचे एक उत्तर देता हूं। संकेत के रूप में आप ऊपर / नीचे वोट बटन पर मँडरा कहते हैं कि "यह मददगार था"। मेरे लिए एक जवाब को वोट देने / उतारने का निर्णय, मेरे द्वारा पूछे गए प्रश्न का उत्तर देने में मददगार था या नहीं।
रयान फार्ले

3
आपने केवल दो सूचियों और दो पुनरावृत्तियों का उपयोग करने में मदद की, मुझे यह पता लगाने की कोशिश में धीमा करना पड़ा कि आपने दो सूचियों का उपयोग क्यों किया और परिणाम classlistपर पहले पुनरावृत्ति पर सीधे जोड़ नहीं दिया asm.GetTypes()
6

20

एक विशिष्ट विधानसभा के लिए, नामस्पेस और क्लासनेम:

var assemblyName = "Some.Assembly.Name"
var nameSpace = "Some.Namespace.Name";
var className = "ClassNameFilter";

var asm = Assembly.Load(assemblyName);
var classes = asm.GetTypes().Where(p =>
     p.Namespace == nameSpace &&
     p.Name.Contains(className) 
).ToList();

नोट: परियोजना को विधानसभा का संदर्भ देना चाहिए


12

यहां लोडर-एक्सेप्टेंस त्रुटियों के लिए एक फिक्स है जो आपको मिल सकती है यदि एक प्रकार की असेम्बली किसी अन्य असेंबली में टाइप करती है:

// Setup event handler to resolve assemblies
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += new ResolveEventHandler(CurrentDomain_ReflectionOnlyAssemblyResolve);

Assembly a = System.Reflection.Assembly.ReflectionOnlyLoadFrom(filename);
a.GetTypes();
// process types here

// method later in the class:
static Assembly CurrentDomain_ReflectionOnlyAssemblyResolve(object sender, ResolveEventArgs args)
{
    return System.Reflection.Assembly.ReflectionOnlyLoad(args.Name);
}

कि अन्य विधानसभाओं में परिभाषित लोडिंग प्रकारों के साथ मदद करनी चाहिए।

उम्मीद है की वो मदद करदे!


यकीन है कि मददगार लग रहा है, और कम मददगार और कम भ्रामक के बारे में सोच के बिना भी रयान फार्ले के कोड से।
ProfK

आपने मुझे थोड़ी देर के लिए भी भ्रमित किया था। मैं अभी भी केवल अनुमान लगा सकता हूं कि Assembly aसामान सामान्य प्रसंस्करण का प्रतिनिधित्व करता है जो इस घटना को आग लगा सकता है। मैं त्रुटियों के aसाथ मदद करने के लिए कोई उपयोग नहीं देखता LoaderException। क्या मैं सही हू?
ProfK

9

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

Assembly.GetTypes()स्थानीय असेंबली पर काम करता है, या आप पहले किसी असेंबली को लोड कर सकते हैं, फिर उस GetTypes()पर कॉल कर सकते हैं।


2
सही उत्तर के लिए +1। AppDomain.CurrentDomain.GetAssembliesमददगार हो सकता है।
नवाफाल

... और फिर उनके माध्यम से लूप, उन लोगों को फ़िल्टर करना जो नामस्थान से मेल नहीं खाते हैं।
टीजे क्राउडर

ओपी ने विशेष रूप से "एक नामस्थान में कक्षाएं" के लिए कहा, जबकि यह आपको "एक विधानसभा में प्रकार" मिलता है - इसलिए यह उत्तर अधूरा है। सही उत्तर शायद यह एक है , जो सभी विधानसभाओं से केवल कक्षाओं की गणना करता है।
mindplay.dk 10:14

6

@Aku उत्तर की तरह, लेकिन विस्तार विधियों का उपयोग करते हुए:

string @namespace = "...";

var types = Assembly.GetExecutingAssembly().GetTypes()
    .Where(t => t.IsClass && t.Namespace == @namespace)
    .ToList();

types.ForEach(t => Console.WriteLine(t.Name));

5

केवल एक पंक्ति में नाम स्थान के नाम से सभी कक्षाएं प्राप्त करें:

var allClasses = Assembly.GetExecutingAssembly().GetTypes().Where(a => a.IsClass && a.Namespace != null && a.Namespace.Contains(@"..your namespace...")).ToList();

3

नामस्थान वास्तव में रनटाइम के डिजाइन में निष्क्रिय हैं और मुख्य रूप से संगठनात्मक उपकरण के रूप में काम करते हैं। .NET में एक प्रकार का पूरा नाम Namespace और Class / Enum / Etc के होते हैं। संयुक्त। यदि आप केवल एक विशिष्ट असेंबली के माध्यम से जाना चाहते हैं, तो आप असेंबली द्वारा लौटे प्रकारों के माध्यम से लूप करेंगे। GetExportedTypes () प्रकार का मान जाँच रहा है। नाम स्थान । यदि आप वर्तमान AppDomain में लोड सभी असेंबली के माध्यम से जाने की कोशिश कर रहे थे तो इसमें AppDomain.CurrentDomain का उपयोग करना शामिल होगा। GetAssemblies ()


2
//a simple combined code snippet 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace MustHaveAttributes
{
  class Program
  {
    static void Main ( string[] args )
    {
      Console.WriteLine ( " START " );

      // what is in the assembly
      Assembly a = Assembly.Load ( "MustHaveAttributes" );
      Type[] types = a.GetTypes ();
      foreach (Type t in types)
      {

        Console.WriteLine ( "Type is {0}", t );
      }
      Console.WriteLine (
         "{0} types found", types.Length );

      #region Linq
      //#region Action


      //string @namespace = "MustHaveAttributes";

      //var q = from t in Assembly.GetExecutingAssembly ().GetTypes ()
      //        where t.IsClass && t.Namespace == @namespace
      //        select t;
      //q.ToList ().ForEach ( t => Console.WriteLine ( t.Name ) );


      //#endregion Action  
      #endregion

      Console.ReadLine ();
      Console.WriteLine ( " HIT A KEY TO EXIT " );
      Console.WriteLine ( " END " );
    }
  } //eof Program


  class ClassOne
  {

  } //eof class 

  class ClassTwo
  {

  } //eof class


  [System.AttributeUsage ( System.AttributeTargets.Class |
    System.AttributeTargets.Struct, AllowMultiple = true )]
  public class AttributeClass : System.Attribute
  {

    public string MustHaveDescription { get; set; }
    public string MusHaveVersion { get; set; }


    public AttributeClass ( string mustHaveDescription, string mustHaveVersion )
    {
      MustHaveDescription = mustHaveDescription;
      MusHaveVersion = mustHaveVersion;
    }

  } //eof class 

} //eof namespace 

सभी AttributeClassनाम क्या हैं MustHaveAttributes? मुझे परीक्षण से संबंधित कुछ भी नहीं दिखाई देता है कि किसी वर्ग में विशेषताएँ हैं या नहीं। यह सहायक की तुलना में अधिक भ्रामक है।
ProfK

1

काफी सरल

Type[] types = Assembly.Load(new AssemblyName("mynamespace.folder")).GetTypes();
foreach (var item in types)
{
}

और काफी बस सवाल का जवाब नहीं। यह सब कर रहा है, किसी भी विशेष नामस्थान के बावजूद, एक ही विधानसभा में सभी प्रकार की सूची प्राप्त कर रहा है।
इयान
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.