protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);

            if (this.templateScope != null)
            {
                this.templateScope.Dispose();
                this.templateScope = null;
            }
            if (this.eventBufferingScope != null)
            {
                this.eventBufferingScope.Dispose();
                this.eventBufferingScope = null;
            }
        }
        internal static IItemContainer UnfoldTemplate(ISolution solution, IUriReferenceService uriService, IServiceProvider serviceProvider, IProductElement owner, UnfoldVsTemplateSettings settings, bool fromWizard)
        {
            var eventScope = new StoreEventBufferingScope();
            try
            {
                Guard.NotNull(() => solution, solution);
                Guard.NotNull(() => owner, owner);
                Guard.NotNull(() => settings, settings);

                var pathHelper = new UnfoldPathHelper(solution);
                var templateUri = new Uri(settings.TemplateUri);

                // Resolve the designtime template
                tracer.Verbose(
                    Resources.UnfoldVsTemplateCommand_TraceResolvingTemplateUri, owner, settings.TemplateUri.ToString());
                var template = uriService.TryResolveUri<ITemplate>(templateUri);
                if (template == null)
                {
                    throw new FileNotFoundException(
                        string.Format(CultureInfo.CurrentCulture,
                        Resources.UnfoldVsTemplateCommand_ErrorTemplateNotFound, templateUri), settings.TemplateUri.ToString());
                }

                // Resolve the vstemplate
                tracer.Verbose(
                    Resources.UnfoldVsTemplateCommand_TraceResolvingVsTemplateUri, owner, templateUri);
                var vsTemplate = uriService.ResolveUri<IVsTemplate>(templateUri);

                // Get the resolved instance name for the unfolded item
                var unfoldResolver = new UnfoldParentResolver(solution, uriService, owner, vsTemplate);
                unfoldResolver.ResolveParent(settings.TargetPath, settings.TargetFileName);
                var instanceName = unfoldResolver.FileName;
                if (settings.SanitizeName)
                {
                    instanceName = DataFormats.MakePreferredSolutionItemName(instanceName);
                }

                // Ensure name is unique (on disk)
                var solutionItemName = pathHelper.GetUniqueName(instanceName, vsTemplate, unfoldResolver.ParentItem);

                //TODO: We need to close the existing solution (if any) if template is a ProjectGroup 
                // if (vsTemplate.Type == VsTemplateType.ProjectGroup).
                // Otherwise this will fail the unfold

                // Unfold the template
                var generatedItem = template.Unfold(unfoldResolver.ResolveExtension(solutionItemName), unfoldResolver.ParentItem);
                eventScope.Dispose();

                // Perhaps the template unfolded multiple items and none was identifed as the primary
                // (such as in a multi-item item template, with no non-fixed named items)
                if (generatedItem != null)
                {
                    // Prompt user to update element instance name (on name collision) if he is synching names, 
                    // it doesn't make sense to correlate them otherwise
                    if (settings.SyncName)
                    {
                        if (!instanceName.Equals(solutionItemName, StringComparison.OrdinalIgnoreCase))
                        {
                            if (serviceProvider != null)
                            {
                                var shellService = serviceProvider.GetService<IVsUIShell>();
                                if (shellService != null)
                                {
                                    var result = shellService.ShowPrompt(
                                        Resources.UnfoldVsTemplateCommand_PromptToSyncNameTitle,
                                        string.Format(CultureInfo.CurrentCulture,
                                            Resources.UnfoldVsTemplateCommand_PromptToSyncName,
                                            instanceName, solutionItemName));
                                    if (result)
                                    {
                                        owner.InstanceName = solutionItemName;
                                    }
                                }
                                else
                                {
                                    owner.InstanceName = solutionItemName;
                                }
                            }
                            else
                            {
                                owner.InstanceName = solutionItemName;
                            }
                        }
                    }

                    if (!fromWizard)
                    {
                        tracer.Info(
                            Resources.UnfoldVsTemplateCommand_TraceAddReference, owner);

                        SolutionArtifactLinkReference
                            .AddReference(owner, uriService.CreateUri(generatedItem))
                            .Tag = BindingSerializer.Serialize(new ReferenceTag
                        {
                            Tag = settings.Tag ?? string.Empty,
                            SyncNames = settings.SyncName,
                            TargetFileName = settings.TargetFileName
                        });
                    }
                }
                return generatedItem;
            }
            catch (WizardBackoutException) //cancel the unfold if wizard backout
            {
                tracer.Info(
                    Resources.UnfoldVsTemplateCommand_TraceWizardCancelled);
                owner.Delete();
                eventScope.Dispose();
                return null;
            }
            catch (COMException comEx)
            {
                tracer.Error(
                    comEx, Resources.UnfoldVsTemplateCommand_TraceCOMException, owner.InstanceName, settings.TemplateUri);
                owner.Delete();
                eventScope.Dispose();
                throw;
            }
            catch (OperationCanceledException)
            {
                // This exception can be throw explicitly by author code 
                // that wishes to cancel execution, with a friendly user 
                // message, so we can pass this on as-is.
                throw;
            }
            catch (Exception ex) //cancel the unfold if another unexpected exception happened
            {
                tracer.Info(
                    Resources.UnfoldVsTemplateCommand_TraceUnexpectedException, owner.InstanceName, settings.TemplateUri);
                owner.Delete();
                eventScope.Dispose();

                throw new OperationCanceledException(string.Format(
                    CultureInfo.CurrentCulture,
                    Resources.UnfoldVsTemplateCommand_UnexpectedException,
                    settings.TemplateUri, owner.InstanceName, ex.Message));
            }
        }
        public override void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
        {
            base.RunStarted(automationObject, replacementsDictionary, runKind, customParams);

            if (this.PatternManager == null)
            {
                NuPatternCompositionService.Instance.SatisfyImportsOnce(this);
            }

            Guard.NotNull(() => this.PatternManager, this.PatternManager);
            Guard.NotNull(() => this.UriService, this.UriService);

            var safeProductName = GetSafeTemplateName(replacementsDictionary);
            this.templateFile = (string)customParams[0];
            this.templateUri = this.UriService.CreateUri(this.TemplateSchema);

            if (!UnfoldScope.IsActive ||
                !UnfoldScope.Current.HasUnfolded(templateUri.AbsoluteUri))
            {
                var toolkit = FindToolkitOrThrow(this.PatternManager, templateFile);
                var settings = FindTemplateSettingsOrThrow(toolkit, templateUri);

                using (tracer.StartActivity(Resources.InstantiationTemplateWizard_StartingTemplateOriginated, this.TemplateSchema.PhysicalPath))
                {
                    if (settings.CreateElementOnUnfold)
                    {
                        if (!this.Solution.IsOpen && !this.PatternManager.IsOpen)
                        {
                            this.tempStoreFile = Path.GetTempFileName();
                            this.PatternManager.Open(this.tempStoreFile, true);
                        }

                        // We always create the new scope. If there's a wrapping EventBufferingTemplateWizard, we'll just 
                        // hook on top of that. Events that we buffer will not be raised until the outer buffering completes.
                        eventBufferingScope = new StoreEventBufferingScope();

                        this.element = this.PatternManager.CreateProduct(toolkit, safeProductName);
                        var templateAutomation = FindTemplateAutomationOrThrow(this.element, this.templateUri.AbsoluteUri);

                        if (settings.SyncName && settings.TargetFileName.ValueProvider != null)
                            throw new NotSupportedException(Resources.TemplateAutomation_ValueProviderUnsupportedForSyncNames);

                        this.templateScope = new UnfoldScope(
                            templateAutomation,
                            new ReferenceTag
                            {
                                SyncNames = settings.SyncName,
                                TargetFileName = settings.TargetFileName.Value
                            },
                            this.templateUri.AbsoluteUri);

                        if (!templateAutomation.ExecuteWizard())
                        {
                            if (this.templateScope != null)
                            {
                                this.PatternManager.Close();
                                File.Delete(this.tempStoreFile);
                                throw new WizardCancelledException();
                            }
                            else
                            {
                                wizardCancelled = true;
                            }
                        }
                    }
                }
            }
        }