Ну, CreationPolicy
передается как часть метаданных компонента. Это означает, что вы должны иметь возможность запросить метаданные для детали и посмотреть, существует ли она. Способ CreationPolicy
, указанный в метаданных, заключается в использовании полного имени типа System.ComponentModel.Composition.CreationPolicy
в качестве ключа и результата enum в качестве значения. Итак, зная это, мы можем построить метод расширения:
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);
}
Теперь, сначала мы создаем наш ожидаемый ключ, а затем берем экземпляр Lazy<T, TMetadata>
, который включает тип и любые связанные метаданные, как экземпляр Lazy<T, IDictionary<string, object>>
. Если ленивец возвращается как null
, мы можем потерпеть неудачу рано, потому что не было подходящих частей вообще.
Далее мы можем проверить словарь метаданных Lazy.Metadata
, чтобы определить, существуют ли метаданные. Если это произойдет, мы должны привести и сравнить с выбранными нами метаданными. Если это удастся, верните наш экземпляр детали.
Если это не удастся (например, если деталь использует неявное CreationPolicy
из Any
[то есть PartCreationPolicyAttribute
опущено в экспорте]), мы предположим, что деталь может быть возвращено, поскольку мы можем сопоставить политику по умолчанию Any
, поэтому мы можем сопоставить и NonShared
, и Shared
части.
Вы должны иметь возможность использовать это вместо обычного GetExportedValueOrDefault<T>
вызова:
T retrievedComponent = container.GetExportedValueOrDefault<T>(CreationPolicy.NonShared);