private void Generate()

in Sharpmake.Generators/VisualStudio/Csproj.cs [1138:1701]


        private void Generate(
            CSharpProject project,
            List<Project.Configuration> unsortedConfigurations,
            string projectPath,
            string projectFile,
            List<string> generatedFiles,
            List<string> skipFiles
        )
        {
            var itemGroups = new ItemGroups();

            // Need to sort by name and platform
            List<Project.Configuration> configurations = unsortedConfigurations.OrderBy(conf => conf.Name + conf.Platform).ToList();

            var projectFrameworksPerConf = configurations.ToDictionary(conf => conf, GetTargetFramework);
            var projectFrameworks = projectFrameworksPerConf.Values.Distinct().ToList();
            itemGroups.SetTargetFrameworks(projectFrameworks);

            // valid that 2 conf name in the same project don't have the same name
            var configurationNameMapping = new Dictionary<string, Project.Configuration>();
            string assemblyName = null;
            foreach (Project.Configuration conf in configurations)
            {
                if (assemblyName == null)
                    assemblyName = conf.AssemblyName;
                else if (assemblyName != conf.AssemblyName)
                    throw new Error("The assemblyName can't be different between configurations of a same project. {0} != {1} in {2}", assemblyName, conf.AssemblyName, projectFile);

                //set the default outputType
                if (conf.Output == Project.Configuration.OutputType.Exe)
                    conf.Output = Project.Configuration.OutputType.DotNetConsoleApp;
                if (conf.Output == Project.Configuration.OutputType.Dll)
                    throw new Error("OutputType for C# projects must be either DotNetClassLibrary, DotNetConsoleApp or DotNetWindowsApp");

                string projectUniqueName = conf.Name + Util.GetToolchainPlatformString(conf.Platform, conf.Project, conf.Target);

                configurationNameMapping[projectUniqueName] = conf;

                // set generator information
                conf.GeneratorSetOutputFullExtensions(".exe", ".exe", ".dll", ".pdb");
            }

            string outputType;
            switch (configurations[0].Output)
            {
                case Project.Configuration.OutputType.DotNetWindowsApp:
                    outputType = "WinExe";
                    break;
                case Project.Configuration.OutputType.DotNetClassLibrary:
                    outputType = "Library";
                    break;
                case Project.Configuration.OutputType.DotNetConsoleApp:
                default:
                    outputType = "Exe";
                    break;
            }

            string projectTypeGuids = RemoveLineTag;
            switch (project.ProjectTypeGuids)
            {
                case CSharpProjectType.Test:
                    projectTypeGuids = ProjectTypeGuids.ToOption(ProjectTypeGuids.CSharpTestProject);
                    break;
                case CSharpProjectType.Vsix:
                    projectTypeGuids = ProjectTypeGuids.ToOption(ProjectTypeGuids.VsixProject);
                    break;
                case CSharpProjectType.Vsto:
                    projectTypeGuids = ProjectTypeGuids.ToOption(ProjectTypeGuids.VstoProject);
                    break;
                case CSharpProjectType.Wpf:
                    projectTypeGuids = ProjectTypeGuids.ToOption(ProjectTypeGuids.WpfProject);
                    break;
                case CSharpProjectType.Wcf:
                    projectTypeGuids = ProjectTypeGuids.ToOption(ProjectTypeGuids.WcfProject);
                    break;
                case CSharpProjectType.AspNetMvc5:
                    projectTypeGuids = ProjectTypeGuids.ToOption(ProjectTypeGuids.AspNetMvc5Project);
                    break;
            }

            var resolver = new Resolver();

            _projectPath = projectPath;
            _projectPathCapitalized = Util.GetCapitalizedPath(projectPath);
            _projectConfigurationList = configurations;

            var memoryStream = new MemoryStream();
            var writer = new StreamWriter(memoryStream);

            string targetFrameworkString;
            DevEnv devenv = configurations.Select(
                    conf => conf.Target.GetFragment<DevEnv>()).Distinct().Single();

            bool isNetCoreProjectSchema = project.ProjectSchema == CSharpProjectSchema.NetCore ||
                                            (project.ProjectSchema == CSharpProjectSchema.Default &&
                                              (projectFrameworks.Any(x => x.DotNetFramework.IsDotNetCore() || x.DotNetFramework.IsDotNetStandard()) || projectFrameworks.Count > 1)
                                            );

            if (isNetCoreProjectSchema)
            {
                Write(Template.Project.ProjectBeginNetCore, writer, resolver);
                targetFrameworkString = GetTargetFrameworksString(projectFrameworks.ToArray());
            }
            else
            {
                var framework = projectFrameworks.Single().DotNetFramework;
                targetFrameworkString = Util.GetDotNetTargetString(framework);

                using (resolver.NewScopedParameter("toolsVersion", Util.GetToolVersionString(devenv)))
                {
                    // xml begin header
                    switch (devenv)
                    {
                        case DevEnv.vs2015:
                            Write(Template.Project.ProjectBegin, writer, resolver);
                            break;
                        case DevEnv.vs2017:
                        case DevEnv.vs2019:
                        case DevEnv.vs2022:
                            Write(Template.Project.ProjectBeginVs2017, writer, resolver);
                            break;
                        default:
                            throw new ArgumentOutOfRangeException();
                    }
                }
            }

            var preImportCustomProperties = new Dictionary<string, string>(project.PreImportCustomProperties);
            AddPreImportCustomProperties(preImportCustomProperties, project, projectPath);
            WriteCustomProperties(preImportCustomProperties, project, writer, resolver);

            var preImportProjects = new List<ImportProject>(project.PreImportProjects);
            WriteImportProjects(preImportProjects.Distinct(EqualityComparer<ImportProject>.Default), project, configurations.First(), writer, resolver);

            // generate all configuration options onces...
            var options = new Dictionary<Project.Configuration, Options.ExplicitOptions>();

            foreach (Project.Configuration conf in _projectConfigurationList)
            {
                _projectConfiguration = conf;
                Options.ExplicitOptions option = GenerateOptions(project, conf);
                _projectConfiguration = null;
                options.Add(conf, option);
            }

            string netCoreEnableDefaultItems = RemoveLineTag;
            string defaultItemExcludes = RemoveLineTag;
            string targetFrameworkVersionString = "TargetFrameworkVersion";
            string projectPropertyGuid = configurations[0].ProjectGuid;
            string projectConfigurationCondition = Template.Project.DefaultProjectConfigurationCondition;
            if (isNetCoreProjectSchema)
            {
                netCoreEnableDefaultItems = project.EnableDefaultItems.ToString().ToLowerInvariant();

                if (project.DefaultItemExcludes.Count > 0)
                {
                    defaultItemExcludes = string.Join(";", project.DefaultItemExcludes);
                }

                targetFrameworkVersionString = "TargetFramework";
                projectPropertyGuid = RemoveLineTag;
                if (projectFrameworks.Count() > 1)
                {
                    projectConfigurationCondition = Template.Project.MultiFrameworkProjectConfigurationCondition;
                    targetFrameworkVersionString = "TargetFrameworks";
                }
            }

            string restoreProjectStyleString = RemoveLineTag;
            if (project.ExplicitNugetRestoreProjectStyle != false && project.NuGetReferenceType != Project.NuGetPackageMode.VersionDefault)
            {
                switch (project.NuGetReferenceType)
                {
                    case Project.NuGetPackageMode.PackageReference:
                        restoreProjectStyleString = "PackageReference";
                        break;
                    case Project.NuGetPackageMode.PackageConfig:
                    case Project.NuGetPackageMode.ProjectJson:
                        throw new Error($"Unsupported explicit NuGetReferenceType \"{project.NuGetReferenceType}\"");
                    default:
                        throw new ArgumentOutOfRangeException();
                }
            }

            GeneratedAssemblyConfigTemplate generatedAssemblyConfigTemplate = new GeneratedAssemblyConfigTemplate(project.GeneratedAssemblyConfig, isNetCoreProjectSchema, RemoveLineTag);

            using (resolver.NewScopedParameter("project", project))
            using (resolver.NewScopedParameter("guid", projectPropertyGuid))
            using (resolver.NewScopedParameter("options", options[_projectConfigurationList[0]]))
            using (resolver.NewScopedParameter("outputType", outputType))
            using (resolver.NewScopedParameter("targetFramework", targetFrameworkString))
            using (resolver.NewScopedParameter("targetFrameworkVersionString", targetFrameworkVersionString))
            using (resolver.NewScopedParameter("projectTypeGuids", projectTypeGuids))
            using (resolver.NewScopedParameter("assemblyName", assemblyName))
            using (resolver.NewScopedParameter("defaultPlatform", Util.GetToolchainPlatformString(project.DefaultPlatform ?? configurations[0].Platform, project, null)))
            using (resolver.NewScopedParameter("netCoreEnableDefaultItems", netCoreEnableDefaultItems))
            using (resolver.NewScopedParameter("defaultItemExcludes", defaultItemExcludes))
            using (resolver.NewScopedParameter("GeneratedAssemblyConfigTemplate", generatedAssemblyConfigTemplate))
            using (resolver.NewScopedParameter("NugetRestoreProjectStyleString", restoreProjectStyleString))
            using (resolver.NewScopedParameter("GenerateDocumentationFile", project.GenerateDocumentationFile ? "true" : RemoveLineTag))
            {
                Write(Template.Project.ProjectDescription, writer, resolver);
            }

            if (!string.IsNullOrEmpty(project.ApplicationIcon))
            {
                using (resolver.NewScopedParameter("iconpath", Util.PathGetRelative(_projectPathCapitalized, Project.GetCapitalizedFile(project.ApplicationIcon))))
                    Write(Template.ApplicationIcon, writer, resolver);
            }

            string appManifest = project.ApplicationManifest;

            if (!string.IsNullOrEmpty(appManifest))
            {
                appManifest = project.NoneFiles.FirstOrDefault(s => s.EndsWith(appManifest, StringComparison.OrdinalIgnoreCase));
                if (appManifest != null)
                {
                    appManifest = Util.PathGetRelative(_projectPathCapitalized, Project.GetCapitalizedFile(appManifest));
                    using (resolver.NewScopedParameter("applicationmanifest", appManifest))
                        Write(Template.ApplicationManifest, writer, resolver);
                }
            }

            if (!string.IsNullOrEmpty(project.StartupObject))
            {
                using (resolver.NewScopedParameter("startupobject", project.StartupObject))
                    Write(Template.StartupObject, writer, resolver);
            }

            if (project.NoWin32Manifest)
            {
                Write(Template.NoWin32Manifest, writer, resolver);
            }

            if (project.UseMSBuild14IfAvailable)
            {
                Write(Template.MSBuild14PropertyGroup, writer, resolver);
            }

            WriteCustomProperties(project.CustomProperties, project, writer, resolver);

            if (project.ProjectTypeGuids == CSharpProjectType.Wcf)
            {
                string wcfAutoStart = RemoveLineTag;
                if (project.WcfAutoStart.HasValue)
                    wcfAutoStart = project.WcfAutoStart.ToString();
                using (resolver.NewScopedParameter("AutoStart", wcfAutoStart))
                using (resolver.NewScopedParameter("WCFExtensionGUID", ProjectTypeGuids.WindowsCommunicationFoundation.ToString("B").ToUpper()))
                    Write(Template.ProjectExtensionsWcf, writer, resolver);
            }

            if (project.ProjectTypeGuids == CSharpProjectType.Vsto)
            {
                var vstoProject = project as CSharpVstoProject;

                if (vstoProject == null)
                    throw new InvalidDataException("VSTO project was not correctly initialized. Use CSharpVstoProject instead of CSharpProject");

                using (resolver.NewScopedParameter("AddInNamespace", project.RootNamespace))
                using (resolver.NewScopedParameter("OfficeApplication", vstoProject.Application.ToString()))
                using (resolver.NewScopedParameter("OfficeSDKVersion", vstoProject.OfficeSdkVersion))
                    Write(Template.ProjectExtensionsVsto, writer, resolver);
            }

            if (project.ProjectTypeGuids == CSharpProjectType.AspNetMvc5)
            {
                var aspnetProject = project as IAspNetProject;

                if (aspnetProject == null)
                    throw new InvalidDataException("AspNet project was not correctly initialized. Implement IAspNetProject interface");

                Func<bool?, string> toEnableDisable = (value) => value.HasValue ? (value.Value ? "enabled" : "disabled") : RemoveLineTag;

                using (resolver.NewScopedParameter("MvcBuildViews", aspnetProject.MvcBuildViews?.ToString() ?? RemoveLineTag))
                using (resolver.NewScopedParameter("UseIISExpress", aspnetProject.UseIISExpress?.ToString() ?? RemoveLineTag))
                using (resolver.NewScopedParameter("IISExpressSSLPort", aspnetProject.IISExpressSSLPort?.ToString() ?? RemoveLineTag))
                using (resolver.NewScopedParameter("IISExpressAnonymousAuthentication", toEnableDisable(aspnetProject.IISExpressAnonymousAuthentication)))
                using (resolver.NewScopedParameter("IISExpressWindowsAuthentication", toEnableDisable(aspnetProject.IISExpressWindowsAuthentication)))
                using (resolver.NewScopedParameter("IISExpressUseClassicPipelineMode", aspnetProject.IISExpressUseClassicPipelineMode?.ToString() ?? RemoveLineTag))
                using (resolver.NewScopedParameter("UseGlobalApplicationHostFile", aspnetProject.UseGlobalApplicationHostFile?.ToString() ?? RemoveLineTag))
                    Write(Template.Project.ProjectAspNetMvcDescription, writer, resolver);
            }

            var additionalNones = new List<string>();
            if (isNetCoreProjectSchema)
            {
                string launchSettingsJson = LaunchSettingsJson.Generate(_builder, project, projectPath, _projectConfigurationList, generatedFiles, skipFiles);
                if (launchSettingsJson != null)
                    additionalNones.Add(launchSettingsJson);
            }
            else
            {
                // old style cproj.user file
                string projectFilePath = Path.Combine(projectPath, projectFile) + ProjectExtension;
                UserFile uf = new UserFile(projectFilePath);
                uf.GenerateUserFile(_builder, project, _projectConfigurationList, generatedFiles, skipFiles);
            }

            // In case we need to swap out dependencies, we'll cache them here
            Dictionary<string, List<DotNetDependency>> swappedNamesToDependencies = null;

            // configuration general
            foreach (Project.Configuration conf in _projectConfigurationList)
            {
                using (resolver.NewScopedParameter("platformName", Util.GetToolchainPlatformString(conf.Platform, conf.Project, conf.Target)))
                using (resolver.NewScopedParameter("conf", conf))
                using (resolver.NewScopedParameter("project", project))
                using (resolver.NewScopedParameter("targetFramework", GetTargetFrameworksString(projectFrameworksPerConf[conf])))
                using (resolver.NewScopedParameter("projectConfigurationCondition", projectConfigurationCondition))
                using (resolver.NewScopedParameter("target", conf.Target))
                using (resolver.NewScopedParameter("options", options[conf]))
                {
                    Write(Template.PropertyGroupWithConditionStart, writer, resolver);
                    Write(Template.Project.ProjectConfigurationsGeneral, writer, resolver);
                    WriteProperties(conf.CustomProperties, writer, resolver);
                    Write(VsProjCommon.Template.PropertyGroupEnd, writer, resolver);
                }

                foreach (var dependencies in new[] { conf.DotNetPublicDependencies, conf.DotNetPrivateDependencies })
                {
                    foreach (var dependency in dependencies)
                    {
                        var dependencyConfiguration = dependency.Configuration;

                        if (!Util.IsDotNet(dependencyConfiguration))
                            continue;

                        if (dependency.ReferenceSwappedWithOutputAssembly)
                        {
                            // cache swapped dependencies and sort them out later since we have no visibility here regarding
                            // multiple frameworks or optimizations from within a single Project.Configuration
                            // Note: even if preallocating looks tempting, the time it takes to count the entries is actually longer than the time resizing
                            swappedNamesToDependencies ??= new Dictionary<string, List<DotNetDependency>>(StringComparer.Ordinal);
                            if (!swappedNamesToDependencies.TryAdd(dependency.Configuration.AssemblyName, new List<DotNetDependency>{ dependency }))
                            {
                                swappedNamesToDependencies[dependency.Configuration.AssemblyName].Add(dependency);
                            }
                        }
                        else
                        {
                            string dependencyExtension = Util.GetProjectFileExtension(dependencyConfiguration);
                            string projectFullFileNameWithExtension = Util.GetCapitalizedPath(dependencyConfiguration.ProjectFullFileName + dependencyExtension);
                            string relativeToProjectFile = Util.PathGetRelative(_projectPathCapitalized, projectFullFileNameWithExtension);

                            // If dependency project is marked as [Compile], read the GUID from the project file
                            if (dependencyConfiguration.Project.SharpmakeProjectType == Project.ProjectTypeAttribute.Compile && dependencyConfiguration.ProjectGuid == null)
                                dependencyConfiguration.ProjectGuid = ReadGuidFromProjectFile(dependencyConfiguration);

                            // FIXME : MsBuild does not seem to properly detect ReferenceOutputAssembly setting. 
                            // It may try to recompile the project if the output file of the dependency is missing. 
                            // To counter this, the CopyLocal field is forced to false for build-only dependencies. 
                            bool isPrivate = project.DependenciesCopyLocal.HasFlag(Project.DependenciesCopyLocalTypes.ProjectReferences) && dependency.ReferenceOutputAssembly != false;

                            string includeOutputGroupsInVsix = null;
                            if (isPrivate && project.ProjectTypeGuids == CSharpProjectType.Vsix)
                            {
                                // Includes debug symbols of private (i.e. copy local) referenced projects in the VSIX.
                                // This WILL override default values of <IncludeOutputGroupsInVSIX> and <IncludeOutputGroupsInVSIXLocalOnly> from Microsoft.VsSDK.targets,
                                // so if the VSIXs stop working, this may be the cause...
                                includeOutputGroupsInVsix = "DebugSymbolsProjectOutputGroup;BuiltProjectOutputGroup;BuiltProjectOutputGroupDependencies;GetCopyToOutputDirectoryItems;SatelliteDllsProjectOutputGroup";
                            }

                            itemGroups.ProjectReferences.Add(new ItemGroups.ProjectReference
                            {
                                Include = relativeToProjectFile,
                                Name = dependencyConfiguration.ProjectName,
                                Private = isPrivate,
                                Project = new Guid(dependencyConfiguration.ProjectGuid),
                                ReferenceOutputAssembly = dependency.ReferenceOutputAssembly,
                                IncludeOutputGroupsInVSIX = includeOutputGroupsInVsix,
                            });
                        }
                    }
                }

                foreach (var projectReferenceInfo in conf.ProjectReferencesByPath.ProjectsInfos)
                {
                    string projectFullFileNameWithExtension = Util.GetCapitalizedPath(projectReferenceInfo.projectFilePath);
                    string relativeToProjectFile = Util.PathGetRelative(_projectPathCapitalized,
                                                                        projectFullFileNameWithExtension);
                    var projectGuid = projectReferenceInfo.projectGuid;
                    if (projectGuid == Guid.Empty)
                        projectGuid = new Guid(Sln.ReadGuidFromProjectFile(projectReferenceInfo.projectFilePath));

                    itemGroups.ProjectReferences.Add(new ItemGroups.ProjectReference
                    {
                        Include = relativeToProjectFile,
                        Name = Path.GetFileNameWithoutExtension(projectReferenceInfo.projectFilePath),
                        Private =
                            project.DependenciesCopyLocal.HasFlag(
                                Project.DependenciesCopyLocalTypes
                                             .ProjectReferences),
                        Project = projectGuid,
                    });
                }
            }
            
            if(swappedNamesToDependencies is not null)
            {
                foreach (List<DotNetDependency> groupedDependencies in swappedNamesToDependencies.Values)
                {
                    bool isMultiFramework = groupedDependencies.Select(d => d.Configuration.Target.GetFragment<DotNetFramework>()).Distinct().Count() > 1;

                    foreach (var dependency in groupedDependencies.OrderByDescending(d => d.Configuration.Target.GetOptimization()))
                    {
                        TargetFramework targetFramework = GetTargetFramework(dependency.Configuration);
                        string dllPath = Path.Combine(dependency.Configuration.TargetPath, $"{dependency.Configuration.AssemblyName}{dependency.Configuration.DllFullExtension}");
                        var referencesByPath = new ItemGroups.Reference
                        {
                            Include = $"{dependency.Configuration.AssemblyName}{(isMultiFramework ? "-" + GetTargetFrameworksString(targetFramework) : "")}",
                            SpecificVersion = false,
                            HintPath = Util.PathGetRelative(_projectPathCapitalized, dllPath),
                            Private = project.DependenciesCopyLocal.HasFlag(Project.DependenciesCopyLocalTypes.ExternalReferences),
                        };
                        itemGroups.AddReference(targetFramework, referencesByPath);
                    }
                }
            }

            if (project.RunPostBuildEvent != Options.CSharp.RunPostBuildEvent.OnBuildSuccess)
            {
                using (resolver.NewScopedParameter("RunPostBuildEvent", Enum.GetName(typeof(Options.CSharp.RunPostBuildEvent), project.RunPostBuildEvent)))
                    Write(Template.Project.ProjectConfigurationsRunPostBuildEvent, writer, resolver);
            }

            string netCoreSdk = null;
            if (isNetCoreProjectSchema)
            {
                netCoreSdk = "Microsoft.NET.Sdk";
                if (project.NetCoreSdkType != NetCoreSdkTypes.Default)
                    netCoreSdk += "." + project.NetCoreSdkType.ToString();

                using (resolver.NewScopedParameter("importProject", "Sdk.props"))
                using (resolver.NewScopedParameter("sdkVersion", netCoreSdk))
                    Write(Template.Project.ImportProjectSdkItem, writer, resolver);
            }

            GenerateFiles(project, configurations, itemGroups, additionalNones, generatedFiles, skipFiles);

            #region <Choose> section
            Dictionary<string, List<IResolvable>> choiceDict =
                configurations.SelectMany(c => c.ConditionalReferencesByPath.Select(p => new Tuple<string, string>(c.ConditionalReferencesByPathCondition, p)))
                .GroupBy(t => t.Item1).ToDictionary(g => g.Key, g => g.Select(p => new ItemGroups.Reference
                {
                    Include = Path.GetFileNameWithoutExtension(p.Item2),
                    SpecificVersion = false,
                    HintPath = Util.PathGetRelative(_projectPathCapitalized, p.Item2),
                    Private = project.DependenciesCopyLocal.HasFlag(Project.DependenciesCopyLocalTypes.ExternalReferences) ? default(bool?) : false
                } as IResolvable).ToList());

            if (choiceDict.Count != 0)
            {
                Choose choose = new Choose
                {
                    Choices = choiceDict
                };
                writer.Write(choose.Resolve(resolver));
            }
            #endregion

            #region WCF support
            // We need to know if there is any WCFMetadataStorage detected before generating <WCFMetadata>
            if (itemGroups.WCFMetadataStorages.Count > 0)
            {
                writer.Write(Template.ItemGroups.ItemGroupBegin);
                using (resolver.NewScopedParameter("baseStorage", project.WcfBaseStorage))
                    Write(Template.ItemGroups.WCFMetadata, writer, resolver);
                writer.Write(Template.ItemGroups.ItemGroupEnd);
            }
            #endregion

            using (resolver.NewScopedParameter("project", project))
                writer.Write(itemGroups.Resolve(resolver));

            var importProjects = new List<ImportProject>(project.ImportProjects);

            // For .NET Core the default import project is inferred instead of explicit.
            if (isNetCoreProjectSchema)
            {
                importProjects.RemoveAll(i => i.Project == CSharpProject.DefaultImportProject);
            }


            if (project.ProjectTypeGuids == CSharpProjectType.Vsix)
            {
                // Add an extra tag to setup VSIX on VS2017, which is generated on Visual Studio
                // 2017. (This is likely a Microsoft hack to plug 2017 on the 2015 toolset.)
                if (devenv.IsVisualStudio() && devenv >= DevEnv.vs2017)
                    writer.Write(CSproj.Template.Project.VsixConfiguration);
            }

            project.AddCSharpSpecificImportProjects(importProjects, devenv);

            // Add custom .targets files as import projects.
            foreach (string targetsFile in project.CustomTargetsFiles)
            {
                importProjects.AddRange(targetsFile.Select(f => new ImportProject() { Project = targetsFile }));
            }

            WriteImportProjects(importProjects.Distinct(EqualityComparer<ImportProject>.Default), project, configurations.First(), writer, resolver);

            foreach (var element in project.UsingTasks)
            {
                using (resolver.NewScopedParameter("project", project))
                using (resolver.NewScopedParameter("usingTaskElement", element))
                {
                    Write(Template.UsingTaskElement.UsingTask, writer, resolver);
                }
            }

            foreach (var element in project.CustomTargets)
            {
                using (resolver.NewScopedParameter("project", project))
                using (resolver.NewScopedParameter("targetElement", element))
                {
                    if (string.IsNullOrEmpty(element.TargetParameters))
                        Write(Template.TargetElement.CustomTargetNoParameters, writer, resolver);
                    else
                        Write(Template.TargetElement.CustomTarget, writer, resolver);
                }
            }

            if (project.ProjectTypeGuids == CSharpProjectType.AspNetMvc5)
            {
                var aspnetProject = project as IAspNetProject;

                if (aspnetProject == null)
                    throw new InvalidDataException("AspNet project was not correctly initialized. Use AspNetProject instead of CSharpProject");

                using (resolver.NewScopedParameter("UseIIS", aspnetProject.UseIIS?.ToString() ?? RemoveLineTag))
                using (resolver.NewScopedParameter("AutoAssignPort", aspnetProject.AutoAssignPort?.ToString() ?? RemoveLineTag))
                using (resolver.NewScopedParameter("DevelopmentServerPort", aspnetProject.DevelopmentServerPort?.ToString() ?? RemoveLineTag))
                using (resolver.NewScopedParameter("DevelopmentServerVPath", aspnetProject.DevelopmentServerVPath ?? RemoveLineTag))
                using (resolver.NewScopedParameter("IISUrl", aspnetProject.IISUrl ?? RemoveLineTag))
                using (resolver.NewScopedParameter("NTLMAuthentication", aspnetProject.NTLMAuthentication?.ToString() ?? RemoveLineTag))
                using (resolver.NewScopedParameter("UseCustomServer", aspnetProject.UseCustomServer?.ToString() ?? RemoveLineTag))
                using (resolver.NewScopedParameter("SaveServerSettingsInUserFile", aspnetProject.SaveServerSettingsInUserFile?.ToString() ?? RemoveLineTag))
                using (resolver.NewScopedParameter("AspNetMvc5ExtensionGUID", ProjectTypeGuids.AspNetMvc5.ToString("B").ToUpper()))
                    Write(Template.ProjectExtensionsAspNetMvc5, writer, resolver);
            }

            WriteEvents(options, writer, resolver);

            if (isNetCoreProjectSchema)
            {
                using (resolver.NewScopedParameter("importProject", "Sdk.targets"))
                using (resolver.NewScopedParameter("sdkVersion", netCoreSdk))
                    Write(Template.Project.ImportProjectSdkItem, writer, resolver);
            }

            Write(Template.Project.ProjectEnd, writer, resolver);

            // Write the project file
            writer.Flush();

            var cleanMemoryStream = Util.RemoveLineTags(memoryStream, RemoveLineTag);
            var projectFileInfo = new FileInfo(Path.Combine(projectPath, projectFile + ProjectExtension));
            if (_builder.Context.WriteGeneratedFile(project.GetType(), projectFileInfo, cleanMemoryStream))
                generatedFiles.Add(projectFileInfo.FullName);
            else
                skipFiles.Add(projectFileInfo.FullName);

            writer.Close();
        }