2008-09-17 9 views
212

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 ánh trong C#?Bắt tất cả các loại trong không gian tên thông qua sự phản chiếu

+0

bạn có thể chỉnh sửa câu hỏi của mình ... câu hỏi ngữ cảnh có giao tiếp nhiều hơn 'Không gian tên trong C#' – Gishu

+0

Bạn có thể xem [ở đây] (http: // stackoverflow.com/questions/949246/how-to-get-tất cả các lớp-trong-không gian tên). Có 2 mẫu khác nhau. –

Trả lời

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

Lưu ý: Bạn có thể thực hiện việc này với điều kiện bạn đã nhập assembly và NS để tìm kiếm. Các kiểu có thể được định nghĩa trong nhiều assembly và thuộc về cùng một NS. – Gishu

+0

Đó là sự thật Gishu. Tôi cho rằng nó sẽ tốt hơn để vượt qua hội đồng cũng như không gian tên từ hội đồng mà bạn muốn loại bỏ sự mơ hồ. –

+1

"không gian tên" - từ khóa được đặt trước, bạn nên thêm tiền tố @ để làm cho mã này biên dịch – aku

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 namespace có thể nối nhiều cụm, nhưng bạn có thể nhận được tất cả các lớp học trong một lắp ráp và kiểm tra xem nếu họ thuộc về namespace đó.

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

+1

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

+0

... 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. –

270

Mã sau in tên của các lớp theo chỉ định namespace được xác đị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ể được phân tán giữa các mô-đun khác nhau, vì vậy bạn cần phải có được một danh sách các hội đồng đầu tiên.

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

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

12

Dưới đây là bản vá cho lỗi LoaderException bạn có khả năng tìm thấy nếu một trong những loại sublasses một loại trong lắp ráp 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 quy định tại hội đồng khác.

Hy vọng điều đó sẽ hữu ích!

+0

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

+0

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 công cụ 'Assembly a' đại diện cho quá trình xử lý bình thường có thể khiến sự kiện này kích hoạt. Tôi thấy không sử dụng cho 'a' trong việc giúp đỡ với các lỗi' LoaderException'. Tôi có đúng không? – 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

Cái gì'AttributeClass' tên 'MustHaveAttributes' là gì? 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 khó hiểu hơn là hữu ích. – ProfK

5

Cũng giống như câu trả lời @aku, nhưng sử dụng phương pháp khuyến nông:

string @namespace = "..."; 

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

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

Như FlySwat nói, bạn có thể có không gian tên tương tự kéo dài trong nhiều hội (đối với ví dụ System.Collections.Generic). Bạn sẽ phải tải tất cả các assembly nếu chúng chưa được nạp. Vì vậy, để có câu trả lời hoàn chỉnh:

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 khác của miền. Để có được một danh sách của tất cả các lĩnh vực, hãy làm theo this link.

+1

hoạt động tốt - một lời nhắc nhở nhỏ: Tôi đã cố gắng xóa "' && t.Namespace == @ namespace' "- do đó đã cho tôi ** tất cả ** .net assembly :-) – Netsi1964

+0

@ Netsi1964 nếu bạn xóa' && t.Không gian tên == @ namespace' bạn nhận được tất cả * lớp * của * tất cả các assembly *, bao gồm cả .net's. 'GetAssemblies' sẽ cung cấp cho bạn tất cả các assembly, và' GetAssemblies(). SelectMany (t => t.GetTypes()) 'sẽ cung cấp tất cả các kiểu (các lớp, các cấu trúc, vv) từ tất cả các assembly. – nawfal

2

Nhận tất cả các lớp học bằng một phần của tên Namespace chỉ trong một hàng:

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

Đối với một hội cụ thể, với một bộ lọc tên lớp:

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(); 

Lưu ý: Dự án phải tham chiếu đến hội đồng

2

Khá đơn giản

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