2012-10-18 27 views
5

Ứng dụng của tôi bao gồm một số hội đồng cốt lõi và một số cụm mở rộng/plugin. Để cho MEF biết tất cả các phần mà các plugin phải cung cấp, tôi phải tải các assembly này ngay cả khi tôi không bao giờ sử dụng bất kỳ phần nào của chúng. Điều này làm cho ứng dụng mất nhiều thời gian hơn để bắt đầu (nếu tôi sẽ nạp tất cả các assembly khi khởi động) và cũng làm tăng lượng bộ nhớ.Việc tải các cụm/danh mục tải xuống một cách lười biếng

Lý tưởng nhất, tôi sẽ không phải tải các hội đồng cho đến khi tôi thực sự cần chúng. Tôi sẽ chỉ tải dữ liệu xuất của các plugin và khi tôi thực sự cần nhập một phần, MEF sẽ tải assembly và cung cấp một phần.

Tôi thấy rằng có điều gì đó làm khá nhiều thứ tôi vừa viết, nhưng sau khi hỏi về nó trong MEF CachedAssemblyCatalog - Lazy Loading of Assemblies, tôi nhận thấy mã này không được coi là ổn định và không được nhóm MEF duy trì, vì vậy tôi đã quyết định không sử dụng nó.

Câu hỏi của tôi là như thế nào thì tôi có thể đạt được hành vi này:

  • Có khả năng truy cập vào siêu dữ liệu xuất khẩu lắp ráp Plugin mà không cần tải toàn bộ lắp ráp của họ.
  • Tích hợp trong suốt với mã nhập các phần; tức là sử dụng hàng nhập khẩu như thường lệ - một người khác (danh mục chuyên biệt?) sẽ chăm sóc tải các hội đồng nếu cần và cung cấp phần được yêu cầu.
  • Không mất bất kỳ chức năng MEF hiện có như recomposition, loại lười biếng vv

Tôi hoàn toàn tốt với một giải pháp mà đòi hỏi phải phân tích các plugins trước để tạo ra một lắp ráp siêu dữ liệu, tập tin XML hoặc không có điều gì.

Trả lời

2

Nếu bạn chỉ sau khi trì hoãn tải các hội đồng thì bạn có khả năng có thể sử dụng một phần giải pháp cho this question. Bạn sẽ không cần phải lấy tất cả các thông tin được lấy ra trong giải pháp đó. Có lẽ chỉ có tên hợp đồng, tên lắp ráp và liệu bộ phận đó có xuất khẩu hay nhập khẩu hợp đồng hay không. Sau đó, bạn có thể viết một cửa hàng mà nạp các hội đồng như bạn cần đến chúng, ví dụ như thế này:

public sealed class DelayLoadingCatalog : ComposablePartCatalog 
{ 
    // List containing tuples which have the 'contract name' 
    // and the 'assembly name' 
    private readonly List<Tuple<string, string>> m_Plugins 
     = new List<Tuple<string, string>>(); 
    private readonly Dictionary<string, AssemblyCatalog> m_Catalogs 
     = new Dictionary<string, AssemblyCatalog>(); 

    public DelayLoadingCatalog(IEnumerable<Tuple<string, string>> plugins) 
    { 
     m_Plugins.AddRange(plugins); 
    } 

    public override IEnumerable<Tuple<ComposablePartDefinition, ExportDefinition>> GetExports(ImportDefinition definition) 
    { 
     var partsToLoad = m_Plugins 
      .Where(t => t.Item1.Equals(definition.ContractName)); 
     foreach (var part in partsToLoad) 
     { 
      if (!m_Catalogs.ContainsKey(part.Item2.Name)) 
      { 
       var assembly = Assembly.Load(new AssemblyName(part.Item2.Name)); 
       m_Catalogs.Add(part.Item2.Name, new AssemblyCatalog(assembly)); 
      } 
     } 

     return m_Catalogs.SelectMany(p => p.Value.GetExports(definition)); 
    } 

    public override IQueryable<ComposablePartDefinition> Parts 
    { 
     get 
     { 
      throw new NotImplementedException(); 
     } 
    } 
} 

mà sau đó bạn có thể sử dụng như thế này

class Program 
{ 
    public void Init() 
    { 
     var domainSetup = new AppDomainSetup 
     { 
      ApplicationBase = Directory.GetCurrentDirectory(), 
     }; 

     var scanDomain = AppDomain.CreateDomain(
      "scanDomain", 
      null, 
      domainSetup); 
     var scanner = scanDomain.CreateInstanceAndUnwrap(
      typeof(MyScanner).Assembly.FullName, 
      typeof(MyScanner).FullName) as MyScanner; 
     var plugins = scanner.Scan(myPluginsPath); 

     // Make sure we don't have the assemblies loaded anymore ... 
     AppDomain.Unload(scanDomain); 

     var catalog = new DelayLoadingCatalog(plugins); 
     var container = new CompositionContainer(catalog); 

     container.ComposeParts(this); 
    } 

    [Import("MyCoolExport")] 
    public object MyImport 
    { 
     get; 
     set; 
    } 
} 

Ví dụ DelayLoadCatalog không phải là rất thông minh như nó sẽ tiếp tục tìm kiếm thông qua danh sách các bộ dữ liệu. Tối ưu hóa mã không quá khó. Ví dụ, bạn có thể kiểm tra nếu tất cả các assembly đã được nạp và ngừng tìm kiếm thông qua danh sách đó tại thời điểm đó.

+0

Xin chào Petrik, cảm ơn rất nhiều sự giúp đỡ của bạn! Tôi tình cờ gặp câu hỏi mà bạn đã liên kết trước đây và nó đã giúp tôi rất nhiều trong việc giải quyết vấn đề này. Những gì tôi đã kết thúc làm là một cái gì đó tương tự như những gì bạn mô tả ở đó - Tôi tuần tự hóa dữ liệu vào một tập tin và tạo ra một cửa hàng mới mà tiêu thụ tập tin đó. Bằng cách này, tất cả các xuất khẩu bao gồm siêu dữ liệu có sẵn và sử dụng API 'ReflectionModelServices', mọi thứ đều được tải một cách lười biếng. Điều này có vẻ như là cách tốt nhất để đi cho các yêu cầu của tôi. Tôi hy vọng tôi sẽ có thời gian để tự trả lời câu hỏi này với những gì tôi đã làm. Cảm ơn một lần nữa! –

0

Nếu có ai quan tâm, tôi đã tự mình triển khai giải pháp và gần đây đã cung cấp giải pháp trên GitHub. Giải pháp LazyAssemblyLoading cho phép người dùng sắp xếp thông tin phần của một bộ phận và sau đó sử dụng nó để khởi tạo LazyAssemblyCatalog, nó sẽ chỉ tải lắp ráp khi một trong các bộ phận của nó thực sự được yêu cầu, trong khi vẫn cho phép sử dụng siêu dữ liệu như bình thường. nạp vào.

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