リフレクションを介して名前空間のすべての型を取得する


269

C#のリフレクションを使用して、名前空間のすべてのクラスをどのように取得しますか?


質問を編集できますか?サブテキストの質問は、「C#の名前空間」よりも伝達的です
Gishu

あなたは見ることができ、ここで。2つの異なるサンプルがあります。
FatihGÜRDAL2016年

回答:


317

次のコード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

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

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

他のドメインのクラスが必要でない限り、これは機能するはずです。すべてのドメインのリストを取得するには、このリンクをクリックしてください。


1
正常に動作-小さなリマインダー:「&& t.Namespace == @namespace」を削除しようとしました- すべての .netアセンブリを提供した原因です:-)
Netsi1964

@ Netsi1964削除する&& t.Namespace == @namespaceと、.netを含むすべてのアセンブリのすべてのクラスが取得されます。すべてのアセンブリを提供し、すべてのアセンブリからすべてのタイプ(クラス、構造体など)を提供します。GetAssembliesGetAssemblies().SelectMany(t => t.GetTypes())
nawfal 14

DotNet Core 2.2(2.1から)にアップグレードしたところ、このコードが特定のアセンブリで機能しなくなりました。必要なアセンブリがコード内のどこにも参照されていないため、読み込まれませんでした!2.1ではロードされましたが、2.2では遅延ロードがあるようです。
Harvey、

@Harvey .NET Coreにはそもそもappdomainがありますか?
nawfal

@nawfalうん。このコードは以前は2.1で機能していました。Assembly.Load(nameof(NameOfMyNamespace))うまく機能することを使用して、アセンブリの読み込みを強制することがわかりました。
Harvey、

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

注意:上記のコードは何が起こっているのかを示しています。あなたがそれを実装したなら、簡略化されたバージョンを使うことができます:

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
私は意地悪なことをしようとしているわけではありませんが、このコードで見つかったすべての項目について、まったく不要なリストと反復があります。"classlist"変数と
foreach〜

10
@TheXenocideコードサンプルの目的は、コードを記述する「最善の」方法を常に示すことではなく、何かが行われる方法を明確に伝えることを意味します。
ライアンファーリー

4
私は単に教育のためにそれを指摘していました。理解に悪影響を与える悪い例を危険にさらすのではなく、人々が私たちができる最も良い例から学ぶようにすることは私たちの責任です。これは特に有害だと言っているわけではありませんが、私はその感情に同意しません
TheXenocide

4
尋ねられた質問に役に立たない場合は、回答を反対票として投票します。投票ボタンの上/下にカーソルを合わせると表示されるヒントには、「これは役に立ちました」と書かれています。私にとって、回答を賛成/反対投票するかどうかの決定は、質問への回答に役立つかどうかです。
Ryan Farley、

3
2つのリストと2つの反復を使用した唯一のあなたの助けは、なぜ2つのリストを使用したのかを理解しようとするのを遅くclasslistし、最初の反復をasm.GetTypes()結果に直接追加しなかったということです。
ProfK 2014年

20

特定のアセンブリ、NameSpace、およびClassNameの場合:

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

タイプの1つが別のアセンブリのタイプをサブレースする場合に見つかる可能性が高いLoaderExceptionエラーの修正を次に示します。

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

これは、他のアセンブリで定義されている型の読み込みに役立ちます。

お役に立てば幸いです。


確かに、Ryan Farleyのコードよりも、何も考えなくても役立つように見えます。
ProfK 2014年

あなたも私をしばらく混乱させました。私はまだAssembly a、このイベントが発生する原因となる可能性のある通常の処理を表すものであるとしか推測できません。エラーのa手助けには何の役にも立ちませんLoaderException。私は正しいですか?
ProfK 2014年

9

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

Assembly.GetTypes()ローカルアセンブリで機能するか、最初にアセンブリを読み込んでから呼び出すことができますGetTypes()


2
正解は+1。AppDomain.CurrentDomain.GetAssemblies役立ちます。
naffal 2013年

...次に、それらをループして、名前空間に一致しないものを除外します。
TJクラウダー2015年

OPは特に「名前空間のクラス」を要求しましたが、これにより「アセンブリの型」が得られます-したがって、この答えは不完全です。正解は、おそらくすべてのアセンブリからのクラスのみを列挙するこれです。
mindplay.dk

6

@aku answerと同じですが、拡張メソッドを使用します。

string @namespace = "...";

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

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

5

名前空間名の一部によってすべてのクラスを1行で取得します。

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

3

名前空間は、ランタイムの設計では実際にはかなり受動的であり、主に編成ツールとして機能します。.NETの型のフルネームは、名前空間と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 2014年

1

かなりシンプル

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

そして非常に単純に質問に答えない。これにより、特定の名前空間に関係なく、単一のアセンブリ内のすべてのタイプのリストが取得されます。
イアン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.