2011-12-14 2 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는 항상 null로 설정되어 있습니다.

가져 오기가 만족 될 수 있도록 컨테이너 및/또는 제공 업체를 구성하려면 어떻게합니까?

+0

반대 투표를 할 수 없습니다. 하지만 이제는 편집되었습니다. (네, 다른 대답을 말하고 있습니다) – NullUserException

답변

2

내보내기 공급자를 추가 할 때 여전히 컴포지션 컨테이너를 만듭니다. 따라서 아직 작성되지 않은 composition 컨테이너를 사용하여 사용자 정의 내보내기 공급자의 일부를 가져 오는 방법을 알 수 없습니다.

먼저 MyExportProvider를 만드는 데 사용할 임시 CompositionContainer를 만듭니다.

나중에 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

+0

중첩 된 컨테이너를 사용하지 않을 것이고, 예제로 내 대답을 편집 할 것입니다. – Gilles

+0

그러나 MEF가 '발견'과정을 두 번 거쳐야한다는 의미는 아닙니다. – SonOfPirate

1

두 가지 솔루션의 대안으로, 단일 내보내기 공급자에서이를 연결하고 동일한 컨테이너를 사용하여 자체를 구성 할 수 있습니다. 예를 들어, 나는 다음과 같은 계약을 정의한과 수출의 :

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>(); 
    } 
} 

내가 제공을 예를 들어 ICompositionServiceCompositionContainer이 구현되고 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 명시 적으로 당신을 위해 생성되지만, 다른 모든 것들, 그것은 작동합니다.

관련 문제