리플렉션을 통해 네임 스페이스의 모든 유형 가져 오기


268

C #에서 리플렉션을 통해 네임 스페이스의 모든 클래스를 어떻게 얻습니까?


질문을 편집 할 수 있습니까? 하위 텍스트 질문은 'C #의 네임 스페이스'보다 더 의사 소통합니다.
— Gishu

여기서 볼 수 있습니다 . 두 가지 다른 샘플이 있습니다.
— Fatih GÜRDAL

답변:


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

FlySwat이 말했듯이 여러 어셈블리에서 동일한 네임 스페이스를 사용할 수 있습니다 (예 :) System.Collections.Generic. 해당 어셈블리가 아직로드되지 않은 경우 해당 어셈블리를 모두로드해야합니다. 완전한 대답을 얻으려면 :

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

다른 도메인 클래스를 원하지 않는 한 작동합니다. 모든 도메인 목록을 보려면 이 링크를 따르십시오 .


1
잘 작동합니다-작은 알림 : " && t.Namespace == @namespace" 를 제거하려고했습니다.
— of.

@ Netsi1964 제거 && t.Namespace == @namespace하면 .net을 포함한 모든 어셈블리 의 모든 클래스 가 제공 됩니다. GetAssemblies모든 어셈블리 GetAssemblies().SelectMany(t => t.GetTypes())를 제공 하고 모든 어셈블리의 모든 유형 (클래스, 구조체 등)을 제공합니다.
— nawfal

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 통해 "namespacelist"는 "namespacelist"를 반환하는 것과 다른 기능을 제공하지 않습니다.
— TheXenocide

10
@TheXenocide 코드 샘플의 목적은 항상 코드를 작성하는 "최상의"방법을 보여주는 것이 아니라 어떤 일이 어떻게 수행되는지 명확하게 전달하기위한 것입니다.
— Ryan Farley

4
나는 교육을 위해 그것을 지적하고 있었다. 이해에 부정적인 영향을 미치는 나쁜 예를 위험에 빠뜨리기보다는 사람들이 우리가 할 수있는 가장 좋은 예를 통해 배우게하는 것이 우리의 책임입니다. 나는 이것이 특히 해롭다는 말은 아니지만 감정에 동의하지 않는다
— TheXenocide

4
요청 된 질문에 도움이되지 않으면 답을 내려 투표합니다. 위로 / 아래로 투표 버튼 위로 마우스를 가져 가면 "이것이 도움이되었습니다"라는 힌트가 나타납니다. 대답을 위 / 아래로 투표하기로 결정한 것은 질문에 대답하는 데 도움이되었는지 여부입니다.
— Ryan Farley

3
두 개의 목록과 두 개의 반복을 사용하는 유일한 방법은 두 개의 목록을 사용한 이유를 알아 내려고 결과 classlist에 대한 첫 번째 반복에 직접 추가하지 않는 속도를 늦추는 것 asm.GetTypes()입니다.
— ProfK

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

다음은 유형 중 하나가 다른 어셈블리에서 유형을 소급하는 경우 찾을 수있는 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

당신은 또한 잠시 동안 혼란 스러웠습니다. 나는 여전히 Assembly a물건 이이 이벤트를 발생시킬 수있는 정상적인 처리를 나타냅니다. 오류 해결 a에 도움이 되지 않습니다 LoaderException. 내가 맞아?
— ProfK

9

네임 스페이스가 여러 어셈블리를 브리지 할 수 있기 때문에 네임 스페이스에서 모든 유형을 가져올 수는 없지만 어셈블리의 모든 클래스를 가져 와서 해당 네임 스페이스에 속하는지 확인할 수 있습니다.

Assembly.GetTypes()로컬 어셈블리에서 작동하거나 먼저 어셈블리를로드 한 다음 호출 할 수 있습니다 GetTypes().


2
정답은 +1입니다. AppDomain.CurrentDomain.GetAssemblies도움이 될 수 있습니다.
— nawfal

... 그리고 네임 스페이스와 일치하지 않는 것들을 걸러 내면서 그것들을 반복합니다.
— TJ Crowder 2016 년

OP는 특별히 "네임 스페이스의 클래스"를 요청했지만 "어셈블리의 유형"을 표시하므로이 답변은 불완전합니다. 정답은 아마도 모든 어셈블리에서 클래스 만 열거하는 this 입니다.
— mindplay.dk

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에서 유형의 전체 이름은 네임 스페이스와 클래스 / 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)
{
}

그리고 단순히 질문에 대답하지 않습니다. 이 작업은 특정 네임 스페이스에 관계없이 단일 어셈블리의 모든 유형 목록을 가져 오는 것입니다.
— Ian
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.