2009-09-22 35 views
6

Chúng ta đều biết rằng assembly có thể được truy vấn cho các thuộc tính bằng phương thức GetCustomAttributes. Tôi muốn sử dụng điều này để xác định một mô-đun mở rộng cho ứng dụng của tôi. Tuy nhiên, để tránh tải mỗi lắp ráp Tôi thích một cách tiếp cận phòng thủ:Cách lấy các thuộc tính tùy chỉnh từ một assembly không thực sự được nạp

  1. sử dụng Assembly.ReflectionOnlyLoadFrom để biết thêm chi tiết về một hội đồng (? Có nó ModuleAttribute của tôi)

  2. nếu ModuleAttribute được tìm thấy, tôi cuối cùng sẽ được tải nó bằng cách sử Assembly.LoadFrom

Đáng tiếc là dường như không có cách nào để có được những thuộc tính từ một assembly, được nạp vào bối cảnh phản ánh chỉ:

myAssembly.GetCustomAttributes(typeof(ModuleAttribute), false) 

không thành công với một InvalidOperationException ("Thật là bất hợp pháp để phản ánh về các thuộc tính tùy chỉnh của một Loại nạp qua ReflectionOnlyGetType") và

CustomAttributeData.GetCustomAttributes(myAssembly) 

không thành công với ReflectionTypeLoadException vì lắp ráp phụ thuộc không được nạp.

Vậy làm thế nào để có được những thuộc tính mà không

  1. gây ô nhiễm miền ứng dụng của tôi với các loại vô dụng (có thể có hại) bằng cách gọi Assembly.LoadFrom
  2. nhu cầu tải tất cả các assembly tham chiếu
  3. nhu cầu riêng biệt các miền ứng dụng (đã cho nó một thử ngắn, có mùi giống như nhiều hơn PITA)

?

Trả lời

4

Sau khi kiểm tra tất cả các câu trả lời và thực hiện một số nghiên cứu nhiều hơn, có vẻ như đơn giản là không có cách nào để làm những gì Tôi muốn: kiểm tra xem một assembly là một module mở rộng hợp lệ trước khi tải nó vào miền ứng dụng.Hoặc tôi phải tải assembly cần được kiểm tra vào một miền ứng dụng khác, kiểm tra nó ở đó và khi nó tải thành công nó trở lại miền ứng dụng hiện tại của tôi hoặc tôi cần lưu trữ siêu dữ liệu của assembly bên ngoài assembly và tin tưởng siêu dữ liệu này. Tùy chọn một là không thể vì những hạn chế kiến ​​trúc, lựa chọn hai chỉ thay đổi vấn đề nhưng không giải quyết nó.

Có lẽ cách tốt nhất là sử dụng Khung mở rộng được quản lý, nhưng điều này không may là không dễ dàng trong thiết lập hiện tại.

Tôi kết thúc với sự tin tưởng rằng không có gì "xấu" trong thư mục mô-đun và tải mọi thứ (với một số kiểm tra không vượt quá kích thước tệp tối đa và không được tải).

Tuy nhiên, cảm ơn ý kiến ​​của bạn.

0

Nếu tôi là bạn, tôi sẽ lưu trữ siêu dữ liệu trong bộ nhớ cache, ví dụ như các tệp XML. Sử dụng phương pháp này bạn hoàn toàn loại bỏ một nhu cầu để tải bất cứ điều gì. Và bạn có thể lưu trữ ngay cả thông tin, để tính toán những gì bạn cần để thực hiện một hoạt động tốn thời gian.

Bạn có thể tạo các tệp XML được tạo trước hoặc tạo nhanh bằng cách quét tất cả các cụm hiện có.

+1

Không thích phương pháp này, vì nó dựa trên siêu dữ liệu bổ sung. Đây không phải là tốt hơn nhiều so với mã hóa cứng trong đó thư mục một hội đồng với tên tập tin cố định phải được đặt. –

+0

Nó dựa trên siêu dữ liệu được lưu trong bộ nhớ cache, không phụ thuộc vào. Bạn trích xuất siêu dữ liệu từ hội đồng và lưu trữ chúng trong bộ nhớ cache của bạn (tệp XML hoặc bất kỳ thứ gì). Nó là nhanh hơn và tốt hơn sau đó đọc hội đồng. Ngoài ra, cách tiếp cận này có thể mở rộng hơn nhiều vì sau một thời gian bạn sẽ kết thúc với một thứ gì đó, bạn sẽ không thể trích xuất từ ​​assembly mà không tải nó. –

+1

Có thể tôi không giúp bạn, nhưng ai đang tạo bộ đệm siêu dữ liệu? Nó yêu cầu người sáng tạo cung cấp mô tả siêu dữ liệu hợp lệ hoặc tôi để tạo mô tả đó sớm hơn một chút trước khi cố tải mô-đun. Trong cả hai cách, ai đó sẽ cần phải làm điều này và vấn đề là chính xác giống như –

2

Bạn đã xem xét khung công cụ AddIn của microsoft chưa.

Nó cho phép tải mô-đun (AddIns) trong các miền và quy trình ứng dụng khác nhau và truy vấn bằng giao diện trên dữ liệu thuộc tính cụ thể.

Nó có thể không phải là những gì bạn muốn, nhưng có thể đáng xem.

http://msdn.microsoft.com/en-us/library/bb384200.aspx

string[] warnings = AddInStore.Update(Environment.CurrentDirectory); 
Collection<AddInToken> tokens = AddInStore.FindAddIns(typeof(YourType), Environment.CurrentDirectory) 

AddInEnvironment addInEnvironment = new AddInEnvironment(AppDomain.CurrentDomain); 
YourType module = tokens[0].Activate<YourType>(addInEnvironment); 

Và với một chút LINQ bạn có thể truy vấn nó

AddInToken myToken = tokens.FirstOrDefault(currentAddInToken => currentAddInToken.Name.Equals(moduleName)) 
+0

MAF hoặc thậm chí MEF có vẻ là một lựa chọn, vâng. Thật không may điều này sẽ đòi hỏi một sự thay đổi trong thiết kế của các plugin, mà không phải là trực tiếp (và không bắt buộc) được phát triển bởi chúng tôi. –

+0

Nó có thể là một vấn đề nếu các plugin không phải là dễ dàng wrapable –

+0

Nhưng tôi giả sử wraping nó sẽ thách thức nhu cầu của bạn nếu các plugin bên ngoài cần phải được biên dịch lại bởi bạn –

4

Có thể tải các cụm (chỉ phản chiếu) với các phụ thuộc.

AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += (s, e) => Assembly.ReflectionOnlyLoad(e.Name);

sẽ sửa chữa thất bại khi tải, giả sử họ là tất cả trong cùng một thư mục.

+0

Bạn có thể xây dựng với một câu trả lời tốt hơn ở đây? Nghe có vẻ như bạn tìm thấy một công việc xung quanh ... Nhưng tôi không thể làm cho nó hoạt động được. – Vaccano

+1

Đây không phải là giải pháp thay thế nhưng là giải pháp hợp lệ. Khi assembly có chứa các kiểu bắt buộc không thể được phát hiện trong bối cảnh chỉ phản chiếu, sự kiện 'ReflectionOnlyAssemblyResolve' được kích hoạt. Bạn có thể tự lắp ráp sau đó. –

0

Nếu bạn đang truy cập từ xa hoặc sử dụng một cấu hình proxy, bạn sẽ có một cái gì đó tương tự như sau:

AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += (s, e) => OnReflectionOnlyResolve(e, directory); 

Tuy nhiên, nếu bạn đang nhận được một ngoại lệ trên khắp miền, nó có thể trông như thế này:

{System.InvalidOperationException: Nó là bất hợp pháp để phản ánh trên các thuộc tính tùy chỉnh của loại được tải qua ReflectionOnlyGetType (xem Assembly.ReflectionOnly) - sử dụng CustomAttributeData thay thế.

Đây là mã sẽ kích hoạt khỏi dòng thứ nhất.

object[] attributes = assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false); 
return attributes.Length == 0 ? "" : ((AssemblyTitleAttribute) attributes[0]).Title; 

Bạn sẽ cần phải thay đổi nó để sử dụng CustomAttributeData như thế này:

foreach (CustomAttributeData cad in assembly.GetCustomAttributesData().Where(a => a.AttributeType == typeof (AssemblyTitleAttribute))) 
    return cad.ConstructorArguments.FirstOrDefault().Value as String; 
return String.Empty; 
1

Thật câu hỏi cũ, nhưng điều này đã được thể từ NET 2.0. Vấn đề là mọi thứ được nạp vào bối cảnh tải chỉ phản chiếu được triển khai để bạn không thể vô tình kích hoạt tải assembly vào AppDomain hiện tại. Phản ánh các kiểu thuộc tính tùy chỉnh được định nghĩa trong assembly là một trong các kiểu thuộc tính này.

Bạn cần sử dụng CustomAttributeData để xem các thuộc tính tùy chỉnh này.

var assy = Assembly.ReflectionOnlyLoadFrom("MuhPlugin.dll"); 
// gets assembly-level attributes, but you get the idea 
var attrs = CustomAttributeData.GetCustomAttributes(assy); 

CustomAttributeData trường hợp chứa thông tin về thuộc tính, bao gồm các thông số Loại, hàm tạo và thông số được đặt tên. Lưu ý rằng các loại trong đồ thị đối tượng chỉ là sự phản chiếu, vì vậy nếu bạn cố gắng làm những việc với chúng sẽ kích hoạt tải một assembly, nó sẽ ném ra một ngoại lệ quen thuộc.

Bạn có thể sử dụng siêu dữ liệu này về siêu dữ liệu của mình để xác định xem hội đồng được phản ánh có đủ điều kiện cho nhu cầu của bạn hay không.

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