2008-09-17 9 views
212

C#でリフレクションして名前空間のすべてのクラスを取得するにはどうすればよいですか?リフレクションを介して名前空間にすべての型を取得する

+0

あなたの質問を編集することはできますか?サブテキストの質問はC#のネームスペースよりもコミュニケートです – Gishu

+0

[ここ](http:// stackoverflow。com/questions/949246/how-to-get-all-classes-within-namespace)を参照してください。 2つの異なるサンプルがあります。 –

答えて

18
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; 
} 
+0

注:これを行うには、アセンブリと入力したNSを入力する必要があります。タイプは複数のアセンブリで定義することができ、同じNSに属します。 – Gishu

+0

それは本当の紀州です。あいまいさを取り除きたいアセンブリから名前空間だけでなくアセンブリを渡す方が良いと思います。 –

+1

"namespace" - 予約済みのキーワードです。このコードをコンパイルするために@ prefixを追加することをお勧めします。 – aku

9

名前空間が複数のアセンブリを埋めることができますので、あなたは、名前空間内のすべての種類を取得することができませんが、アセンブリ内のすべてのクラスを取得し、彼らはその名前空間に属しているかどうかを確認することができます。

Assembly.GetTypes()がローカルアセンブリで動作するか、アセンブリを最初にロードしてからGetTypes()を呼び出します。

+1

+1です。 AppDomain.CurrentDomain.GetAssembliesが役に立ちます。 – nawfal

+0

...それらをループし、名前空間と一致しないものを除外します。 –

270

次のコードは、現在のアセンブリで定義されている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)); 
3

名前空間は、実際にはランタイムの設計においてはむしろ受動的であり、主に組織ツールとして機能します。 .NETの型のフルネームは、NamespaceとClass/Enum/Etcで構成されます。組み合わせる。特定のアセンブリだけを実行したい場合は、アセンブリによって返された型をループするだけです。 GetExportedTypes()タイプの値をチェックしています。 Namespace。現在のAppDomainに読み込まれたすべてのアセンブリを処理しようとしている場合は、AppDomain.CurrentDomainを使用する必要があります。

// 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); 
} 

他のアセンブリで定義されたロードタイプを支援する必要がありますタイプのいずれかが別のアセンブリ内のタイプをサブクラスを場合GetAssemblies()

12

は、ここでは一般的ですLoaderExceptionエラーの修正です。

希望に役立ちます!

+0

ライアン・ファーリーのコードよりも役立ちますが、それほど参考にならず、混乱も少なくなります。 – ProfK

+0

あなたはまた、しばらく私を混乱させました。私はまだ 'Assembly a'物がこの出来事を引き起こすかもしれない正常な処理を表すと推測することができます。私は、 'LoaderException'エラーを助けるのに' a'を使用していません。私は正しい? – ProfK

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 
+0

'MustHaveAttributes'という名前の'AttributeClass'とは何ですか?クラスに属性があるかどうかをテストすることは何も見ません。これは参考になるよりも混乱します。 – ProfK

5
だけ@akuの答えのような

が、使用して拡張メソッドは:FlySwatが言うように

string @namespace = "..."; 

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

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

、あなたは(例えばSystem.Collections.Generic用)複数のアセンブリにまたがる同じ名前空間を持つことができます。これらのアセンブリがまだロードされていない場合は、それらをすべてロードする必要があります。だから完全な答え:

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

これは、他のドメインのクラスを必要としない限り動作します。すべてのドメインのリストを取得するには、this link.

+1

はうまく動作します - 私は "&& t.Namespace == @ namespace'"を削除しようとしました - どちらのofcauseが** all ** .netアセンブリを与えました:-) – Netsi1964

+0

'&& tを削除するとNetsi1964。Namespace == @ namespace' .netを含む*すべてのアセンブリ*の*クラス*を取得します。 'GetAssemblies'はすべてのアセンブリを提供し、' GetAssemblies()。SelectMany(t => t.GetTypes()) 'はすべてのアセンブリからすべての型(クラス、構造体など)を与えます。 – nawfal

2

に従うだけで1行の名前空間名の一部ですべてのクラスを取得します。具体的な組み立てのため

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

、クラス名フィルタを持つ:

var asm = Assembly.Load("Some.Assembly.Name"); 
var nameSpace = "Some.Namespace.Name"; 

var classes = asm.GetTypes().Where(p => 
    p.Namespace == nameSpace && 
    p.Name.Contains("ClassNameFilter") 
).ToList(); 

注:プロジェクトが参照する必要があります

2

非常に簡単組立

Type[] types = Assembly.Load(new AssemblyName("mynamespace.folder")).GetTypes(); 
foreach (var item in types) 
{ 
} 
関連する問題