2011-12-14 54 views
1

我想知道如何在我的自定義ExportProvider可以有進口。以下是我正在嘗試執行的一個示例:滿足進口自定義ExportProvider

public class MyExportProvider : ExportProvider 
{ 
    private List<Export> _exports; 

    [Import()] 
    private IConfig _config; 

    public MyExportProvider() 
     base() 
    { 
     _exports = new List<Export>(); 
    } 

    protected override IEnumerable<Export> GetExportsCore(ImportDefinition definition, 
                  AtomicComposition composition) 
    { 
     if (!_exports.Any()) 
      Initialize(); 

     return _exports.Where(x => definition.IsConstraintSatisfiedBy(s.Definition); 
    } 

    private void Initialize() 
    { 
     var contractName = typeof(MyObject).FullName; 

     var exportDefinition = new ExportDefinition(contractName, null); 
     var export = new Export(exportDefinition,() => new MyObject(_config)); 

     _exports.Add(export); 
    } 
} 

我在創建CompositionContainer時添加了提供程序。

不幸的是,導入永遠不會滿足。我可以通過設置AllowDefaults = true來看到這一點,所以我的提供程序已創建,但_config始終爲空。

如何配置容器和/或提供商以便滿足導入?

+0

我們不能撤回選票。但是現在你可以自己動手編輯了(是的,我正在談論另一個答案) – NullUserException 2012-01-06 17:52:30

回答

2

當您添加導出提供程序時,您仍在創建組合容器。因此我看不出如何使用尚未創建的組合容器來導入自定義導出提供程序的某些部分。

我會做的是首先創建一個臨時的CompositionContainer,用於創建MyExportProvider。

之後使用MyExportProvider創建您的第二個最終的CompositionContainer,該應用程序的其餘部分將使用它。

編輯:

// this is your real container, only shown here for reference 
    CompositionContainer container; 

    public void BootstrapContainerMethod() 
    {   
     // Replace this part with the catalogs required to create your export provider. 
     var catalog = new AggregateCatalog(); 
     catalog.Catalogs.Add(new DirectoryCatalog("./bin", "*.dll")); 

     // Your temporary container, declared here in local scope 
     // will be disposed because of using 
     using (var bootstrapContainer = new CompositionContainer(catalog)) 
     { 
      var myExportProvider = bootstrapContainer.GetExportedValue<IMyExportProvider>(); 

      // create your real container and optionnally add catalogs (not shown here) 
      container = new CompositionContainer(myExportProvider); 
     } 
    } 

您也可以從另一個角度來考慮這個問題。你真的需要在自定義的ExportProvider中導入嗎?我不知道你的要求,但也許你可以不做進口。

+0

這樣的嵌套容器是否有任何性能或內存問題? – SonOfPirate 2011-12-21 14:46:59

1

作爲雙CompositionContainer解決方案的替代方案,您可以將其連接到單個導出提供程序中,並使用相同的容器自行組合。舉個例子,我已經定義了以下的合同,它的出口:

public interface ILogger 
{ 
    void Log(string message); 
} 

[Export(typeof(ILogger))] 
public class ConsoleLogger : ILogger 
{ 
    public void Log(string message) 
    { 
     Console.WriteLine(message); 
    } 
} 

而且隨着我的榜樣ExportProvider,我希望能夠導入它的一個實例:

public class TestExportProvider : ExportProvider 
{ 
    private readonly object _lock = new object(); 
    private bool _initialised; 

    [Import] 
    public ILogger Logger { get; set; } 

    public void SetCompositionService(ICompositionService service) 
    { 
     if (service == null) throw new ArgumentNullException("service"); 

     lock (_lock) 
     { 
      if (!_initialised) 
      { 
       InitialiseProvider(service); 
      } 
     } 
    } 

    private void InitialiseProvider(ICompositionService service) 
    { 
     service.SatisfyImportsOnce(this); 
     _initialised = true; 
    } 

    protected override IEnumerable<Export> GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition) 
    { 
     if (_initialised) 
     { 
      Logger.Log("Getting available exports for '" + definition.ContractName + "'"); 

      // Do work here.); 
      return Enumerable.Empty<Export>(); 
     } 

     return Enumerable.Empty<Export>(); 
    } 
} 

我提供ICompositionService的實例,CompositionContainer實現了這個實例,當我撥打SetCompositionService時,我會執行首次初始化。它會檢查它是否已經被初始化,如果沒有,則繼續並自行調用SatisfyImportsOnce方法。

我們將這樣組裝起來,這樣的事情:

// Build our catalog. 
var catalog = new AssemblyCatalog(typeof(Program).Assembly); 

// Create our provider. 
var provider = new TestExportProvider(); 

// Create our container. 
var container = new CompositionContainer(catalog, provider); 

// Register the composition service to satisfy it's own imports. 
provider.SetCompositionService(container); 

很明顯,你將無法使用任何進口,你ExportProvider將明確地爲您創建的,但對於一切,它應該工作。