2011-10-10 6 views
1

MEF를 DI 컨테이너로 사용하는 IoC 랩퍼가 있습니다. 랩퍼의 적용 가능한 스니 j이 아래에 나와 있습니다.비 기여 수입에 대해 RequiredCreationPolicy를 지정하십시오.

public static bool TryGetComponent<T>(out T component) 
{ 
    CompositionContainer container = RetrieveContainer(); 

    T retrievedComponent = container.GetExportedValueOrDefault<T>(); 
    if (retrievedComponent.Equals(default(T))) 
    { 
     component = default(T); 
     return false; 
    } 

    component = retrievedComponent; 

    return true; 
} 

CompositionContainer에서 내 보낸 구성 요소의 대부분은 CreationPolicy를 "Any"로 지정합니다.

[PartCreationPolicy(CreationPolicy.Any)] 

내가 만드는 유형의 경우 MEF가 내 보낸 형식을 비공유 인스턴스로 제공하기 위해 다음 가져 오기 특성을 쉽게 사용할 수 있습니다.

[Import(RequiredCreationPolicy = CreationPolicy.NonShared)] 

하지만, 내 IOC의 래퍼도 클래스에 의해 사용되어야하기 때문에 MEF 또는 가져 오기 속성의 중 하나를 사용하지 않고 인스턴스를 수출 유형을 얻기 위해 내 IOC의 API를 사용해야합니다. 프로그래밍 방식으로 CompositionContainer를 GetExports 및 GetExportedValues에 사용할 때 CreationPolicy를 지정하는 방법이 필요합니다.. 가져 오기 속성을 사용하지 않고도이 작업을 수행 할 수 있습니까?

답변

4

하는 것은 다음 만들어보십시오 당신의 자신의 정의 ContractBasedImportDefinition. 생성자에 대한 매개 변수 중 하나는 필수 생성 정책을 나타내는 CreationPolicy입니다. 뭔가 같은 : 물론

container.GetExports(new ContractBasedImportDefinition(
    AttributedModelServices.GetContractName(type), 
    AttributedModelServices.GetTypeIdentity(type), 
    null, 
    ImportCardinality.ZeroOrMore, 
    false, 
    false, 
    CreationPolicy.NonShared)); 

당신이 필요에 따라 매개 변수를 조정할 수 있지만 이것은 당신이 올바른 방향으로 움직이고하고 모든로 표시되어 어떤 부분의 공유 안 버전을 만들 컨테이너의 원인이됩니다 (인 기본값).

+0

감사합니다 웨스,이 정확히 내가 뭘 찾고 있어요. – Xacron

1

음, CreationPolicy은 구성 요소의 메타 데이터의 일부로 전달됩니다. 즉, 파트의 메타 데이터를 쿼리하여 해당 파트가 있는지 확인할 수 있어야합니다. CreationPolicy이 메타 데이터에 지정된 방법은 전체 유형 이름 System.ComponentModel.Composition.CreationPolicy을 키로 사용하고 enum 결과를 값으로 사용하는 것입니다. 첫째로 우리는 우리의 예상 키를 만든 다음 우리는 유형과 Lazy<T, IDictionary<string, object>> 인스턴스와 연관된 메타 데이터를 포함하는 Lazy<T, TMetadata> 인스턴스를 잡아 지금

public static T GetExportedValueOrDefault<T>(this CompositionContainer container, CreationPolicy creationPolicy) 
{ 
    var metadataKey = typeof(CreationPolicy).FullName; 

    var lazy = container.GetExportedValueOrDefault<T, IDictionary<string, object>>(); 
    if (lazy == null) 
    return default(T); 

    if (lazy.Metadata.ContainsKey(metadataKey)) 
    { 
    // If the creation policy matches the required, return. 
    if (((CreationPolicy)lazy.Metadata[metadataKey]) == creationPolicy) 
     return lazy.Value; 
    } 
    else 
    { 
    // Return the value as we assume it satisfies the default CreationPolicy = Any 
    return lazy.Value; 
    } 

    return default(T); 
} 

: 그래서,이 알고 우리는 확장 방법을 구축 할 수 있습니다. 게으름이 null으로 돌아 오면 일치하는 부분이 전혀 없으므로 일찍 실패 할 수 있습니다.

다음으로 메타 데이터 사전 Lazy.Metadata을 확인하여 메타 데이터가 존재하는지 확인할 수 있습니다. 그렇다면 선택한 메타 데이터와 비교하고 비교해야합니다. 성공하면 part 인스턴스를 반환합니다. 즉 성공하지 못한 경우 (부품이 Any의 암시 CreationPolicy이 [즉, PartCreationPolicyAttribute 내보내기 생략] 사용하는 경우 예)

, 우리는 우리가 할 수있는 파트가 반환 될 수 있음을 가정합니다 기본 Any 생성 정책에서 일치하므로 NonSharedShared 부분을 모두 일치시킬 수 있습니다.

당신은 정상 GetExportedValueOrDefault<T> 호출 대신이를 사용할 수 있어야합니다 : 당신이 정말 정확하게 RequiredCreationPolicy = 공유 안와 ImportAttribute을 가진 것처럼 같은 컨테이너를 조회 할 경우

T retrievedComponent = container.GetExportedValueOrDefault<T>(CreationPolicy.NonShared); 
+0

Matthew, 빠른 응답에 감사드립니다. 당신이 제시 한 것은 약속 한 것처럼 보였습니다. 그러나 예상대로 행동하지는 않습니다. 기본값 'CreationPolicy'는 실제로 '모두'입니다. 이는 내보내기에 PartCreationPolicy가 지정되지 않은 경우 MEF가 사용하는 것입니다. 그러나 가져 오기에 RequiredCreationPolicy가 지정되지 않은 경우 MEF는 기본적으로 'Shared'를 사용합니다. 그래서 'container.GetExportedValueOrDefault (CreationPolicy.NonShared)'을 호출하면 내보내기가 '공유'를 지정하지 않은 경우에도 메타 데이터 일치는 없으며 어떤 부분도 보류되지 않습니다. 예상되는 동작이 아닙니다. – Xacron

+0

@Steve - 아, [RequiredCreationPolicy 및 PartCreationPolicy 동작이 혼란스러워 질 가능성이 있음]을 알지 못했습니다. 업데이트됩니다. –

+0

@ 스티브 - 효과가 있습니까? 'Any'라고 가정하여 업데이트되었으며 메타 데이터가 제공되지 않은 부분을 만족시킬 것입니까? –

관련 문제