نکته: آشنایی با مفاهیم MEF برای درک بهتر مطالب الزامی است.
*در صورتی که با مفاهیم MEF آشنایی ندارید میتوانید از اینجا شروع کنید.
در MEF سه نوع PartCreationPolicy وجود دارد:
#1 Shared : آبجکت مورد نظر فقط یک بار در کل طول عمر Composition Container ساخته میشود.(Singleton)
#2 NonShared : آبجکت مورد نظر به ازای هر درخواست دوباره نمونه سازی میشود.
#3 Any : از حالت پیش فرض CompositionContainar برای نمونه سازی استفاده میشود که همان مورد اول است(Shared)
در اکثر پروژهها ساخت نمونه اشیا به صورت Singleton میسر نیست و باعث اشکال در پروژه میشود. برای حل این مشکل باید PartCreationPolicy رو برای هر شی مجزا تعریف کنیم. برای مثال
[Export] [PartCreationPolicy( CreationPolicy.NonShared )] internal class ShellViewModel : ViewModel<IShellView> { private readonly DelegateCommand exitCommand; [ImportingConstructor] public ShellViewModel( IShellView view ) : base( view ) { exitCommand = new DelegateCommand( Close ); } }
برای حل این مسئله بهتر است که رفتار Composition Container رو در هنگام نمونه سازی تغییر دهیم. یعنی آبجکتها به صورت پیش فرض به صورت NonShared تولید شوند و در صورت نیاز به نمونه Shared این Attribute رو در کلاس مورد نظر استفاده کنیم. کافیست از کلاس Composition Container که قلب MEF محسوب میشود ارث برده و رفتار مورد نظر را Override کنیم. برای نمونه :
public class CustomCompositionContainer : CompositionContainer { public CustomCompositionContainer(ComposablePartCatalog catalog) : base(catalog) { } protected override IEnumerable<Export> GetExportsCore(ImportDefinition definition) { definition = AdaptDefinition(definition); return base.GetExportsCore(definition); } private ImportDefinition AdaptDefinition(ImportDefinition definition) { ContractBasedImportDefinition namedDefinition = definition as ContractBasedImportDefinition; if (namedDefinition != null && namedDefinition.RequiredCreationPolicy == CreationPolicy.Any) { definition = new ContractBasedImportDefinition(namedDefinition.ContractName, namedDefinition.RequiredMetadata, namedDefinition.Cardinality, namedDefinition.IsRecomposable, namedDefinition.IsPrerequisite, CreationPolicy.NonShared); } return definition; } }
حال فقط کافیست در پروژه به جای استفاده از CompositionContainer از CustomCompositionContainer استفاده کنیم.