2010-02-18 25 views
5

Giả sử tôi có một phương pháp nhà máy, mà muốn xây dựng một thể hiện của một loại được chọn tại thời gian chạy thông qua sự phản ánh. Giả sử thêm rằng phương thức factory của tôi là mã generic mà không tham chiếu trực tiếp assembly có chứa kiểu được chỉ định, mặc dù nó sẽ được chạy từ bên trong một ứng dụng có tham chiếu cần thiết được tham chiếu.Làm thế nào tôi có thể nhận được một loại từ một hội đồng tham chiếu thông qua sự phản ánh

Tôi làm cách nào để viết mã có thể tìm thấy loại này? Nếu tôi làm như sau

public object CreateInstance(string typeName) 
{ 
    Type desiredType = Assembly.GetExecutingAssembly().GetType(typename); 

    // Instantiate the type... 
} 

điều này dường như không thành công vì loại không được xác định trong hội đồng thực thi. Nếu tôi có thể nhận được tất cả các hội đồng có sẵn tại thời gian chạy, tôi có thể lặp qua chúng và tìm thấy một trong những có chứa loại tôi muốn. Nhưng tôi không thể nhìn thấy một cách để làm điều đó. AppDomain.CurrentDomain.GetAssemblies() trông đầy hứa hẹn, nhưng không trả lại tất cả các hội đồng mà tôi đã tham chiếu trong dự án của tôi.

Chỉnh sửa: Một số người đã chỉ ra rằng tôi cần tải lắp ráp. Vấn đề là, đoạn mã này không biết lắp ráp nó nên tải, vì tôi đang cố gắng viết mã này theo cách mà nó không phụ thuộc vào các hội đồng khác.

Tôi cố tình bỏ qua các chi tiết của typeName, vì ánh xạ từ chuỗi này sang thực tế phức tạp hơn trong mã thực của tôi. Trong thực tế, loại được xác định bởi một thuộc tính tùy chỉnh có chứa chuỗi được chỉ định, nhưng nếu tôi có thể giữ danh sách các loại, tôi không có vấn đề với việc hạn chế danh sách theo loại mong muốn.

+0

Giá trị trong typeName là gì? Có phải tên đầy đủ không? –

Trả lời

9

Cuộc gọi đến AppDomain.CurrentDomain.GetAssemblies() chỉ trả về tập hợp các DLL hiện đang được tải vào AppDomain. DLL được nạp vào một quá trình CLR theo yêu cầu; do đó nó sẽ không bao gồm tất cả các DLL được tham chiếu trong dự án của bạn cho đến khi một thực sự được sử dụng.

Điều bạn có thể làm là bắt buộc lắp ráp vào quá trình bằng cách sử dụng biểu thức typeof. Ví dụ:

var force1 = typeof(SomeTypeInTheProject).Assembly; 
var force2 = typeof(SomeTypeInProject2).Assembly; 
+0

Cảm ơn, điều này dường như làm việc - và vì tất cả các loại có thể là trong cùng một hội đồng, tôi chỉ phải làm điều đó cho một loại. Mặc dù nó cảm thấy khá xấu xí. –

2

AppDomain.CurrentDomain.GetAssemblies() chỉ trả về các cụm được tải. Vì vậy, bạn cần tải assembly đã tham chiếu đó nếu nó chưa được tải.

10

Bạn có thể sử dụng GetReferencedAssemblies và lặp qua tất cả các loại cho đến khi bạn tìm thấy loại bạn đang tìm kiếm.

var t = Assembly 
    .GetExecutingAssembly() 
    .GetReferencedAssemblies() 
    .Select(x => Assembly.Load(x)) 
    .SelectMany(x => x.GetTypes()).First(x => x.FullName == typeName); 

Mặc dù nó có thể không có hiệu suất cao nhất. Sau đó, một lần nữa, bạn bằng cách sử dụng phản chiếu.

+0

Ý tưởng hay. Nó không hoàn toàn phù hợp với tôi, vì hội đồng không được tham chiếu trực tiếp, nhưng bị gián tiếp tham chiếu bởi hội đồng gọi điện; có lẽ tôi sẽ có thể tìm thấy nó bằng cách đệ quy gọi .GetReferencedAssemblies() trên mỗi hội đồng tìm thấy (và bắt đầu từ .GetEntryAssembly() chứ không phải là .GetExecutingAssembly()). Và có, nó không tuyệt vời cho hiệu suất, nhưng đó là OK cho tôi vì nó là mã khởi động và chỉ chạy một lần. –

Các vấn đề liên quan