Vui lòng đọc toàn bộ câu hỏi. Tôi có một tình huống duy nhất với một số ràng buộc mà tôi muốn giải quyết.Đang tải một bản lắp ráp và áp dụng biến vị ngữ trên các loại của nó trong một tên miền ứng dụng khác
Trong mã của tôi, tôi có cây biểu thức được biên soạn thành Predicate<System.Type>
. Mục tiêu của tôi là tải một assembly mà không khóa nó (nó là assembly đầu ra của project, được xây dựng lại liên tục), áp dụng vị từ này vào danh sách các kiểu của nó và lấy lại danh sách kiểu kết quả tên:
// this is what I need:
return assembly.GetTypes().Where(t => predicate(t)).Select(t => t.FullName);
Hội đồng này phải được tải trong một miền ứng dụng khác, bởi vì tôi muốn dỡ bỏ nó ngay sau khi tôi nhận được thông tin tôi yêu cầu.
Đây là nơi nó trở nên phức tạp. Có một số vấn đề tôi đang gặp phải:
Nếu tôi tải cụm từ trong miền ứng dụng khác và chỉ cần trả về một mảng của tất cả các loại của nó, để tôi có thể áp dụng vị từ đó trong miền ứng dụng chính của mình được marshalled trở lại appdomain chính của tôi tôi nhận được một FileNotFoundException
, nói rằng lắp ráp này không được tìm thấy. Điều này làm cho sence, bởi vì lắp ráp chỉ được nạp trong appdomain khác tôi tạo ra. Tải nó cũng trong appdomain chính sẽ đánh bại mục đích.
Nếu, cách khác, tôi cố gắng chuyển vị từ này vào miền ứng dụng khác, để áp dụng nó và lấy lại một chuỗi các chuỗi (tên đầy đủ), tôi nhận được SerializationException: "Cannot serialize delegates over unmanaged function pointers, dynamic methods or methods outside the delegate creator's assembly."
, vì biến vị ngữ là một phương thức động (được biên dịch) từ một cây biểu thức).
Tải nó trong tên miền phụ chính sẽ không có vấn đề gì, nhưng vì không thể dỡ một assembly đã tải mà không dỡ toàn bộ appdomain, ngay khi assembly sẽ thay đổi (sau khi xây dựng lại), bất kỳ nỗ lực nào để nạp assembly với cùng một tên sẽ dẫn đến một ngoại lệ.
Bối cảnh:
Tôi đang xây dựng một plugin cho ReSharper gọi Agent Mulder. Ý tưởng đằng sau plugin là phân tích đăng ký DI/IoC Container trong giải pháp của bạn và giúp ReSharper tìm ra cách sử dụng các loại đã đăng ký qua DI Container (bạn có thể xem video ngắn về cách hoạt động của here).
Phần lớn, phân tích đăng ký vùng chứa là đơn giản - tôi chỉ phải phát hiện đủ thông tin để biết loại bê tông nào bị ảnh hưởng. Trong ví dụ này với Castle Windsor: Component.For<IFoo>().ImplementedBy<Foo>()
loại kết quả là hiển nhiên, như vậy là AllTypes.FromThisAssembly().BasedOn<IFoo>()
- cung cấp cho tôi đủ thông tin để đánh giá các loại cụ thể sẽ bị ảnh hưởng bởi dòng này. Tuy nhiên, hãy xem xét đăng ký này tại Lâu đài Windsor:
container.Register(Classes
.FromAssemblyInDirectory(new AssemblyFilter(".").FilterByName(an => an.Name.StartsWith("Ploeh.Samples.Booking")))
.Where(t => !(t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Dispatcher<>)))
.WithServiceAllInterfaces());
(source)
Đây là thông tin phụ thuộc vào một vị đó sẽ chỉ được đánh giá trong thời gian chạy.
Vì tất cả những gì tôi có thể làm là phân tích tĩnh điều này, tôi có trong tay đại diện AST của ReSharper (được gọi là PSI trong ReSharper) của biểu thức lambda từ mệnh đề Where
. Tôi có thể chuyển đổi AST này thành một cây biểu thức LINQ, sau đó biên dịch nó thành một đại biểu.
Ý tưởng của tôi là tải cụm đầu ra (được xác định bởi bộ mô tả FromAssembly*
) qua phản xạ và áp dụng đại biểu này cho các loại lắp ráp để có được tên kiểu (tôi chỉ cần tên). Điều này sẽ phải được đánh giá lại mỗi lần lắp ráp thay đổi, quá (Tôi không quan tâm vào thời điểm này về hiệu suất). Trong kết luận, trừ khi ai đó có thể đề xuất một cách tốt hơn để xác định các loại bị ảnh hưởng bởi vị từ, tôi muốn biết cách làm điều này với sự phản chiếu (không may là tôi đã không coi các trình đọc siêu dữ liệu khác, vì tôi muốn phải bằng cách nào đó chuyển đổi biểu thức lambda AST thành một biến vị ngữ của kiểu dữ liệu khác nhau, và tôi không biết nếu có tồn tại một chuyển đổi 1-đến-1).
Cảm ơn bạn đã đọc. Câu hỏi này sẽ có tiền thưởng 500 điểm khi nó có sẵn.
Nếu 'Expression' là serializable, bạn có thể tạo ra các' Predicate' delegate như một 'Expression' và chuyển nó qua ranh giới appdomain và biên dịch nó trong appdomain 'từ xa'. Nhưng thật đáng buồn, đó không phải là trường hợp đó: ( – leppie
@leppie Vâng, tôi đã nghĩ về việc sắp xếp lại biểu thức và chuyển nó đi, bạn nói đúng, nó không đơn giản như vậy ... –