public void RunStarted(object automationObject,
            Dictionary<string, string> replacementsDictionary,
            WizardRunKind runKind, object[] customParams)
        {
            // This instance may be reused -- reinitialize each time
            this._project = null;

            this._dte2 = automationObject as DTE2;
            if (this._dte2 == null)
            {
                this.TerminateWizard(Resources.WizardError_No_DTE);
            }

            // Get active project.  Throws if null.
            Project project = this.ActiveProject;

            ITypeDiscoveryService typeDiscoveryService = this.GetTypeDiscoveryService(project);
            if (typeDiscoveryService == null)
            {
                this.TerminateWizard(Resources.BusinessLogicClass_Error_No_TypeDiscoveryService);
            }

            // Check if the project has a reference to the assembly that has DbDomainService, supporting DbContext.
            VSProject vsproj = project.Object as VSProject;
            bool allowDbContext = false;
            if (vsproj != null) 
            {
                allowDbContext = vsproj.References.Cast<Reference>().Any(r => String.Equals(r.Name, BusinessLogicClassConstants.DbDomainServiceAssemblyShortName));
            }

            // Get the list of available ObjectContexts, DataContexts, and optionally DbContexts.
            bool foundDbContext = false;
            IEnumerable<Type> candidates = this.GetCandidateTypes(typeDiscoveryService, allowDbContext, out foundDbContext);

            // Ensure the user entered a non-null file name
            string fileName = replacementsDictionary["$rootname$"];
            fileName = fileName.Trim();
            if (string.IsNullOrEmpty(fileName))
            {
                this.TerminateWizard(Resources.WizardError_Empty_Filename);
            }

            // Class name is file name minus extension.  Validate not empty.
            string className = Path.GetFileNameWithoutExtension(fileName);
            if (string.IsNullOrEmpty(className))
            {
                this.TerminateWizard(Resources.WizardError_Empty_Filename);
            }

            // We infer language from extension
            string extension = Path.GetExtension(fileName);
            bool isVb = extension.EndsWith("vb", StringComparison.OrdinalIgnoreCase);
            string language = isVb ? "VB" : "C#";

            Property rootNamespaceProperty = project.Properties.Item("RootNamespace");
            string namespaceName = rootNamespaceProperty == null ? null : (string)(rootNamespaceProperty.Value);
            if (string.IsNullOrEmpty(namespaceName))
            {
                this.TerminateWizard(Resources.BusinessLogicClass_Error_No_RootNamespace);
            }

            // Extract VB root namespace for code gen.
            // If non-empty, it means we want to avoid generating namespaces that begin with it.
            string rootNamespace = isVb ? namespaceName : string.Empty;

            // Get the name of the assembly produced by the current project
            Property assemblyNameProperty = project.Properties.Item("AssemblyName");
            string assemblyName = assemblyNameProperty == null ? null : (string)(assemblyNameProperty.Value);
            if (string.IsNullOrEmpty(assemblyName))
            {
                this.TerminateWizard(Resources.BusinessLogicClass_Error_No_AssemblyName);
            }

            // We extract all the context types from the TypeDiscovery service and will pass
            // those to another AppDomain for analysis
            IEnumerable<Type> candidateTypes = candidates.Where(t => CodeGenUtilities.IsValidGenericTypeParam(t));

            // We need the project path for the ClientBuildManager source folder
            string projectPath = project.FullName;
            if (string.IsNullOrEmpty(projectPath))
            {
                this.TerminateWizard(Resources.BusinessLogicClass_No_Project_Path);
            }
            string projectDirectory = Path.GetDirectoryName(projectPath);
            try
            {
                IVsHelp help = this.GetService(typeof(IVsHelp)) as IVsHelp;
                // Strategy: we instantiate the contexts in another AppDomain so they can load the assembly outside of the current
                // Visual Studio root AppDomain.  The main reason for this is the ability to reopen the DSWizard onto modified
                // client assemblies and see modified types.  If they were loaded into the root AppDomain, we would not be able to
                // reload.  The BusinessLogicViewModel is IDisposable and controls the other AppDomain's lifetime.
                using (BusinessLogicViewModel businessLogicViewModel = new BusinessLogicViewModel(projectDirectory, className, language, rootNamespace, assemblyName, candidateTypes, help))
                {
                    businessLogicViewModel.ShowDbContextWarning = false; // foundDbContext; //Removed by CDB //TODO: remove commented out section

                    // Intercept exceptions to report to VS UI.
                    businessLogicViewModel.ExceptionHandler = delegate(Exception ex)
                    {
                        this.ShowError(ex.Message);
                        throw ex;
                    };

                    // Invoke the wizard UI now
                    this._dialog = new BusinessLogicClassDialog();
                    this._dialog.Model = businessLogicViewModel;

                    IVsUIShell uiShell = this.GetService(typeof(IVsUIShell)) as IVsUIShell;
                    IntPtr dialogOwnerHwnd = default(IntPtr);
                    int result = uiShell.GetDialogOwnerHwnd(out dialogOwnerHwnd);
                    if (result == 0 && dialogOwnerHwnd != default(IntPtr))
                    {
                        WindowInteropHelper windowHelper = new WindowInteropHelper(this._dialog);
                        windowHelper.Owner = dialogOwnerHwnd;
                    }
                    this._dialog.ShowInTaskbar = false;

                    this._dialog.ShowDialog();
                    bool success = this._dialog.DialogResult.HasValue && this._dialog.DialogResult.Value;
                    this._dialog.Model = null;

                    // If user cancels dialog, cancel wizard
                    if (!success)
                    {
                        throw new WizardCancelledException();
                    }

                    // Capture some model state to we can dispose the contexts and models
                    ContextViewModel currentContext = businessLogicViewModel.CurrentContextViewModel;
                    this._isClientAccessEnabled = currentContext != null && currentContext.IsClientAccessEnabled;
                    this._isODataEndpointEnabled = currentContext != null && currentContext.IsODataEndpointEnabled;

                    // Compute a namespace that includes folder names
                    namespaceName = this.ComputeNamespace();

                    // User said OK -- so let's generate the code
                    IGeneratedCode generatedCode = businessLogicViewModel.GenerateBusinessLogicClass(namespaceName);

                    replacementsDictionary.Add("$generatedcode$", generatedCode.SourceCode);
                    this.AddReferences(generatedCode.References);
                    this._businessLogicCode = generatedCode;

                    // If user elected metadata classes, do that into a separate file
                    if (businessLogicViewModel.IsMetadataClassGenerationRequested)
                    {
                        // The null namespace asks to generate into the entity types own namespaces
                        IGeneratedCode generatedMetadataCode = businessLogicViewModel.GenerateMetadataClasses(null /* optionalSuffix */);
                        replacementsDictionary.Add("$generatedmetadatacode$", generatedMetadataCode.SourceCode);
                        this.AddReferences(generatedMetadataCode.References);
                        this._generateMetadataFile = generatedMetadataCode.SourceCode.Length > 0;
                        this._metadataCode = generatedMetadataCode;
                    }
                    else
                    {
                        this._generateMetadataFile = false;
                    }
                }
            }
            finally
            {
                this._dialog = null;
            }
        }
Esempio n. 2
0
        public void RunStarted(object automationObject,
                               Dictionary <string, string> replacementsDictionary,
                               WizardRunKind runKind, object[] customParams)
        {
            // This instance may be reused -- reinitialize each time
            this._project = null;

            this._dte2 = automationObject as DTE2;
            if (this._dte2 == null)
            {
                this.TerminateWizard(Resources.WizardError_No_DTE);
            }

            // Get active project.  Throws if null.
            Project project = this.ActiveProject;

            ITypeDiscoveryService typeDiscoveryService = this.GetTypeDiscoveryService(project);

            if (typeDiscoveryService == null)
            {
                this.TerminateWizard(Resources.BusinessLogicClass_Error_No_TypeDiscoveryService);
            }

            // Check if the project has a reference to the assembly that has DbDomainService, supporting DbContext.
            VSProject vsproj         = project.Object as VSProject;
            bool      allowDbContext = false;

            if (vsproj != null)
            {
                allowDbContext = vsproj.References.Cast <Reference>().Any(r => String.Equals(r.Name, BusinessLogicClassConstants.DbDomainServiceAssemblyShortName));
            }

            // Get the list of available ObjectContexts, DataContexts, and optionally DbContexts.
            bool foundDbContext           = false;
            IEnumerable <Type> candidates = this.GetCandidateTypes(typeDiscoveryService, allowDbContext, out foundDbContext);

            // Ensure the user entered a non-null file name
            string fileName = replacementsDictionary["$rootname$"];

            fileName = fileName.Trim();
            if (string.IsNullOrEmpty(fileName))
            {
                this.TerminateWizard(Resources.WizardError_Empty_Filename);
            }

            // Class name is file name minus extension.  Validate not empty.
            string className = Path.GetFileNameWithoutExtension(fileName);

            if (string.IsNullOrEmpty(className))
            {
                this.TerminateWizard(Resources.WizardError_Empty_Filename);
            }

            // We infer language from extension
            string extension = Path.GetExtension(fileName);
            bool   isVb      = extension.EndsWith("vb", StringComparison.OrdinalIgnoreCase);
            string language  = isVb ? "VB" : "C#";

            Property rootNamespaceProperty = project.Properties.Item("RootNamespace");
            string   namespaceName         = rootNamespaceProperty == null ? null : (string)(rootNamespaceProperty.Value);

            if (string.IsNullOrEmpty(namespaceName))
            {
                this.TerminateWizard(Resources.BusinessLogicClass_Error_No_RootNamespace);
            }

            // Extract VB root namespace for code gen.
            // If non-empty, it means we want to avoid generating namespaces that begin with it.
            string rootNamespace = isVb ? namespaceName : string.Empty;

            // Get the name of the assembly produced by the current project
            Property assemblyNameProperty = project.Properties.Item("AssemblyName");
            string   assemblyName         = assemblyNameProperty == null ? null : (string)(assemblyNameProperty.Value);

            if (string.IsNullOrEmpty(assemblyName))
            {
                this.TerminateWizard(Resources.BusinessLogicClass_Error_No_AssemblyName);
            }

            // We extract all the context types from the TypeDiscovery service and will pass
            // those to another AppDomain for analysis
            IEnumerable <Type> candidateTypes = candidates.Where(t => CodeGenUtilities.IsValidGenericTypeParam(t));

            // We need the project path for the ClientBuildManager source folder
            string projectPath = project.FullName;

            if (string.IsNullOrEmpty(projectPath))
            {
                this.TerminateWizard(Resources.BusinessLogicClass_No_Project_Path);
            }
            string projectDirectory = Path.GetDirectoryName(projectPath);

            try
            {
                IVsHelp help = this.GetService(typeof(IVsHelp)) as IVsHelp;
                // Strategy: we instantiate the contexts in another AppDomain so they can load the assembly outside of the current
                // Visual Studio root AppDomain.  The main reason for this is the ability to reopen the DSWizard onto modified
                // client assemblies and see modified types.  If they were loaded into the root AppDomain, we would not be able to
                // reload.  The BusinessLogicViewModel is IDisposable and controls the other AppDomain's lifetime.
                using (BusinessLogicViewModel businessLogicViewModel = new BusinessLogicViewModel(projectDirectory, className, language, rootNamespace, assemblyName, candidateTypes, help))
                {
                    businessLogicViewModel.ShowDbContextWarning = false; // foundDbContext; //Removed by CDB //TODO: remove commented out section

                    // Intercept exceptions to report to VS UI.
                    businessLogicViewModel.ExceptionHandler = delegate(Exception ex)
                    {
                        this.ShowError(ex.Message);
                        throw ex;
                    };

                    // Invoke the wizard UI now
                    this._dialog       = new BusinessLogicClassDialog();
                    this._dialog.Model = businessLogicViewModel;

                    IVsUIShell uiShell         = this.GetService(typeof(IVsUIShell)) as IVsUIShell;
                    IntPtr     dialogOwnerHwnd = default(IntPtr);
                    int        result          = uiShell.GetDialogOwnerHwnd(out dialogOwnerHwnd);
                    if (result == 0 && dialogOwnerHwnd != default(IntPtr))
                    {
                        WindowInteropHelper windowHelper = new WindowInteropHelper(this._dialog);
                        windowHelper.Owner = dialogOwnerHwnd;
                    }
                    this._dialog.ShowInTaskbar = false;

                    this._dialog.ShowDialog();
                    bool success = this._dialog.DialogResult.HasValue && this._dialog.DialogResult.Value;
                    this._dialog.Model = null;

                    // If user cancels dialog, cancel wizard
                    if (!success)
                    {
                        throw new WizardCancelledException();
                    }

                    // Capture some model state to we can dispose the contexts and models
                    ContextViewModel currentContext = businessLogicViewModel.CurrentContextViewModel;
                    this._isClientAccessEnabled  = currentContext != null && currentContext.IsClientAccessEnabled;
                    this._isODataEndpointEnabled = currentContext != null && currentContext.IsODataEndpointEnabled;

                    // Compute a namespace that includes folder names
                    namespaceName = this.ComputeNamespace();

                    // User said OK -- so let's generate the code
                    GeneratedCode generatedCode = businessLogicViewModel.GenerateBusinessLogicClass(namespaceName);

                    replacementsDictionary.Add("$generatedcode$", generatedCode.SourceCode);
                    this.AddReferences(generatedCode.References);
                    this._businessLogicCode = generatedCode;

                    // If user elected metadata classes, do that into a separate file
                    if (businessLogicViewModel.IsMetadataClassGenerationRequested)
                    {
                        // The null namespace asks to generate into the entity types own namespaces
                        GeneratedCode generatedMetadataCode = businessLogicViewModel.GenerateMetadataClasses(null /* optionalSuffix */);
                        replacementsDictionary.Add("$generatedmetadatacode$", generatedMetadataCode.SourceCode);
                        this.AddReferences(generatedMetadataCode.References);
                        this._generateMetadataFile = generatedMetadataCode.SourceCode.Length > 0;
                        this._metadataCode         = generatedMetadataCode;
                    }
                    else
                    {
                        this._generateMetadataFile = false;
                    }
                }
            }
            finally
            {
                this._dialog = null;
            }
        }