Ответ 1
SatisyImportsOnce
будет составлять тип без регистрации его для перекомпоновки. Таким образом, если вы намерены использовать тип без поддержки для перекомпоновки, вы можете использовать SatisfyImportsOnce
, и он будет выполнять работу как обычно, но любые изменения в контейнере (новые детали добавлены или детали удалены), тогда ваш экземпляр выиграл ' t автоматически будет предложено предложить эти новые детали.
В вашем случае вы используете:
[ImportMany(typeof(ICustomRenderer), AllowRecomposition = true)]
... но через SatisfyImportsOnce
этот импорт не будет рекомпостирован.
Если вас не беспокоит рекомпозиция, вы можете изменить вложение конструктора использования кода, чтобы вы могли:
[ImportingConstructor]
public FormPartCustomatorFactory(IEnumerable<Lazy<ICustomRenderer, ICustomRendererMetadata>> renderers)
{
if (renderers == null)
throw new ArgumentNullException("renderers");
_renderers = renderers.ToDictionary(r => r.Metadata.Name, r => r);
}
Причина, по которой я предлагаю впрыск конструктора, заключается в том, что набор экземпляров Lazy<ICustomRenderer, ICustomRendererMetadata>
- это явная зависимость, которую требует ваш тип, поэтому было бы лучше создать экземпляр вашего типа в пригодном для использования состоянии, а не создавать экземпляры, а затем потребовать дополнительный шаг, чтобы подготовить его к использованию в первый раз.
Это делает ваш тип FormPartCustomatorFactory
более надежным. С этой целью, если бы вы изменили конструктор как таковой, то ваш метод его создания не работал бы. Вместо этого вы можете воспользоваться функциональностью управления жизненным циклом MEF, поэтому, возможно, измените свой тип следующим образом:
public interface IFormPartCustomatorFactory
{
ICustomRenderer Find(string name);
}
[Export(typeof(IFormPartCustomerFactory)), PartCreationPolicy(CreationPolicy.Shared)]
public class FormPartCustomatorFactory : IFormPartCustomatorFactory
{
private IEnumerable<Lazy<ICustomRenderer, ICustomRendereMetadata>> _renderers;
[ImportingConstructor]
public FormPartCustomatorFactory(IEnumerable<Lazy<ICustomRenderer, ICustomRendererMetadata>> renderers)
{
if (renderers == null)
throw new ArgumentNullException("renderers");
_renderers = renderers;
}
public ICustomRenderer Find(string name)
{
return _renderers
.Where(r => r.Metadata.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)
.Select(r => r.Value)
.FirstOrDefault();
}
}
Выполнение этого способа означает, что ваш тип не зависит от MEF, его можно использовать без него, его более проверяемым, а CompositionContainer
будет управлять временем жизни части, в этом случае CreationPolicy.Shared
(который по умолчанию для экспортируемых типов), использует однолетнюю стратегию жизни. Затем вы можете импортировать экземпляр IFormPartCustomator
, вы импортируете один и тот же экземпляр singleton.
Я также утверждаю, что вызов его Factory
, возможно, неверен, поскольку factory предназначен для создания новых экземпляров, тогда как ваш тип будет создавать только один экземпляр каждого ICustomRenderer
. Если это предполагаемое поведение, возможно, было бы лучше назвать FormPartCustomatorService
, который реализует интерфейс IFormPartCusomatorService
? Если вы хотите каждый раз создавать новые экземпляры, вы можете посмотреть ExportFactory<ICustomRenderer, ICustomRendererMetadata>
.