Bắt tất cả các loại trong một không gian tên thông qua sự phản chiếu


269

Làm thế nào để bạn có được tất cả các lớp trong một không gian tên thông qua sự phản chiếu trong C #?


bạn có thể chỉnh sửa câu hỏi của mình không ... câu hỏi ẩn ý có tính giao tiếp cao hơn 'Không gian tên trong C #'
Gishu

Bạn có thể nhìn vào đây . Có 2 mẫu khác nhau.
Fatih GÜRDAL

Câu trả lời:


317

Mã sau in tên của các lớp được chỉ namespaceđịnh trong hội đồng hiện tại.
Như những người khác đã chỉ ra, một không gian tên có thể nằm rải rác giữa các mô-đun khác nhau, vì vậy trước tiên bạn cần có một danh sách các cụm.

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

Như FlySwat nói, bạn có thể có cùng một không gian tên trải dài trong nhiều cụm (ví dụ System.Collections.Generic). Bạn sẽ phải tải tất cả các hội đồng đó nếu chúng chưa được tải. Vì vậy, để có một câu trả lời đầy đủ:

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

Điều này sẽ hoạt động trừ khi bạn muốn các lớp của các miền khác. Để có được danh sách tất cả các tên miền, hãy theo liên kết này.


1
hoạt động tốt - một lời nhắc nhỏ: Tôi đã cố xóa " && t.Namespace == @namespace" - vì lý do đó đã cho tôi tất cả các cụm .net :-)
Netsi1964

@ Netsi1964 nếu bạn xóa, && t.Namespace == @namespacebạn nhận được tất cả các lớp của tất cả các hội đồng , bao gồm cả .net. GetAssembliessẽ cung cấp cho bạn tất cả các hội đồng, và GetAssemblies().SelectMany(t => t.GetTypes())sẽ cung cấp cho tất cả các loại (lớp, cấu trúc, v.v.) từ tất cả các hội đồng.
nawfal

Tôi đã nâng cấp lên DotNet Core 2.2 (từ 2.1) và mã này đã ngừng hoạt động cho phần lắp ráp cụ thể của tôi. Tập hợp tôi muốn không được tham chiếu ở bất cứ đâu trong mã nên không được tải! Trong 2.1 nó đã được tải, nhưng 2.2 dường như có tải lười biếng?
Harvey

@Harvey .NET Core có appdomain để bắt đầu không?
nawfal

@nawfal Vâng. Mã này đã làm việc trước đây trong 2.1. Tôi thấy rằng tôi buộc tải một hội đồng bằng cách sử dụng Assembly.Load(nameof(NameOfMyNamespace))hoạt động tốt.
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;
}

NB: Đoạn mã trên minh họa những gì đang diễn ra. Nếu bạn thực hiện nó, một phiên bản đơn giản hóa có thể được sử dụng:

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
Tôi không cố gắng để có ý nghĩa, nhưng có một danh sách và lặp lại hoàn toàn không cần thiết thông qua tất cả các mục được tìm thấy trong mã này; biến "danh sách lớp" và tìm kiếm thông qua "
tênpacelist

10
@TheXenocide mục đích của một mẫu mã không phải lúc nào cũng có nghĩa là hiển thị cách "tốt nhất" để viết mã, nhưng để truyền đạt rõ ràng cách thức thực hiện một cái gì đó.
Ryan Farley

4
Tôi chỉ chỉ ra nó vì mục đích giáo dục; đó là trách nhiệm của chúng tôi để làm cho những người vật chất học hỏi từ ví dụ tốt nhất chúng ta có thể thay vì mạo hiểm với một ví dụ xấu ảnh hưởng tiêu cực đến sự hiểu biết. Tôi không nói điều này đặc biệt là bất lợi, nhưng tôi không đồng ý với tình cảm
TheXenocide

4
Tôi bỏ phiếu trả lời nếu nó không hữu ích cho câu hỏi đã được hỏi. Gợi ý bạn thấy khi bạn di chuột qua nút bỏ phiếu lên / xuống cho biết "Điều này rất hữu ích". Đối với tôi, quyết định lên / xuống bỏ phiếu trả lời là liệu nó có hữu ích trong việc trả lời câu hỏi hay không.
Ryan Farley

3
Điều duy nhất bạn sử dụng hai danh sách và hai lần lặp giúp là làm tôi chậm lại khi cố gắng tìm ra lý do tại sao bạn sử dụng hai danh sách và không chỉ thêm thẳng classlistvào lần lặp đầu tiên trong asm.GetTypes()kết quả.
ProfK

20

Đối với một hội cụ thể, NameSpace và 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();

Lưu ý: Dự án phải tham khảo lắp ráp


12

Đây là một sửa chữa cho các lỗi LoaderException mà bạn có thể tìm thấy nếu một trong các kiểu con một kiểu trong một cụm khác:

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

Điều đó sẽ giúp với các loại tải được xác định trong các hội đồng khác.

Mong rằng sẽ giúp!


Chắc chắn có vẻ hữu ích, và ít hữu ích hơn và ít gây nhầm lẫn hơn mã của Ryan Farley ngay cả khi không nghĩ về nó.
ProfK

Bạn cũng đã làm tôi bối rối trong một thời gian mặc dù. Tôi vẫn chỉ có thể đoán rằng những Assembly athứ đại diện cho quá trình xử lý thông thường có thể gây ra sự kiện này. Tôi thấy không có ích gì atrong việc giúp đỡ với LoaderExceptionlỗi. Tôi có đúng không
ProfK

9

Bạn sẽ không thể có được tất cả các loại trong một không gian tên, bởi vì một không gian tên có thể kết nối nhiều cụm, nhưng bạn có thể lấy tất cả các lớp trong một cụm và kiểm tra xem chúng có thuộc không gian tên đó không.

Assembly.GetTypes()hoạt động trên lắp ráp cục bộ hoặc bạn có thể tải một cụm đầu tiên sau đó gọi GetTypes()nó.


2
+1 cho câu trả lời đúng. AppDomain.CurrentDomain.GetAssembliescó thể hữu ích
nawfal

... Và sau đó lặp qua chúng, lọc ra những cái không khớp với không gian tên.
TJ Crowder

OP đặc biệt yêu cầu "các lớp trong một không gian tên", trong khi điều này giúp bạn "nhập vào một cụm" - vì vậy câu trả lời này không đầy đủ. Câu trả lời đúng có lẽ là câu này , chỉ liệt kê các lớp, từ tất cả các hội đồng.
mindplay.dk

6

Giống như @aku trả lời, nhưng sử dụng các phương thức mở rộng:

string @namespace = "...";

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

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

5

Nhận tất cả các lớp theo một phần của tên không gian chỉ trong một hàng:

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

3

Không gian tên thực sự khá thụ động trong thiết kế thời gian chạy và phục vụ chủ yếu như các công cụ tổ chức. Tên đầy đủ của một loại trong .NET bao gồm Không gian tên và Class / Enum / Etc. kết hợp. Nếu bạn chỉ muốn đi qua một hội đồng cụ thể, bạn chỉ cần lặp qua các kiểu được trả về bởi hội đồng. GetExportedTypes () kiểm tra giá trị của loại. Không gian tên . Nếu bạn đang cố gắng đi qua tất cả các hội đồng được tải trong AppDomain hiện tại, nó sẽ liên quan đến việc sử dụng AppDomain.CienDomain. 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 

Là gì AttributeClasstên MustHaveAttributestất cả về? Tôi thấy không có gì liên quan đến việc kiểm tra xem một lớp có thuộc tính hay không. Điều này là khó hiểu hơn là hữu ích.
ProfK

1

Khá đơn giản

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

Và khá đơn giản là không trả lời câu hỏi. Tất cả điều này đang làm là nhận được một danh sách tất cả các loại trong một cụm, không phân biệt bất kỳ không gian tên cụ thể nào.
Ian
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.