public ApplicationHostContext(IServiceProvider hostServices, string projectDirectory, string packagesDirectory, string configuration, FrameworkName targetFramework, IAssemblyLoadContextFactory loadContextFactory = null, bool skipLockFileValidation = false) { ProjectDirectory = projectDirectory; Configuration = configuration; RootDirectory = Runtime.ProjectResolver.ResolveRootDirectory(ProjectDirectory); ProjectResolver = new ProjectResolver(ProjectDirectory, RootDirectory); FrameworkReferenceResolver = new FrameworkReferenceResolver(); ProjectGraphProvider = new ProjectGraphProvider(hostServices); _serviceProvider = new ServiceProvider(hostServices); PackagesDirectory = packagesDirectory ?? NuGetDependencyResolver.ResolveRepositoryPath(RootDirectory); var referenceAssemblyDependencyResolver = new ReferenceAssemblyDependencyResolver(FrameworkReferenceResolver); NuGetDependencyProvider = new NuGetDependencyResolver(new PackageRepository(PackagesDirectory)); var gacDependencyResolver = new GacDependencyResolver(); ProjectDependencyProvider = new ProjectReferenceDependencyProvider(ProjectResolver); var unresolvedDependencyProvider = new UnresolvedDependencyProvider(); var projectName = PathUtility.GetDirectoryName(ProjectDirectory); Project project; if (ProjectResolver.TryResolveProject(projectName, out project)) { Project = project; } else { throw new InvalidOperationException( string.Format("Unable to resolve project '{0}' from {1}", projectName, ProjectDirectory)); } var projectLockJsonPath = Path.Combine(ProjectDirectory, LockFileReader.LockFileName); var lockFileExists = File.Exists(projectLockJsonPath); var validLockFile = false; if (lockFileExists) { var lockFileReader = new LockFileReader(); _lockFile = lockFileReader.Read(projectLockJsonPath); validLockFile = _lockFile.IsValidForProject(project); // When the only invalid part of a lock file is version number, // we shouldn't skip lock file validation because we want to leave all dependencies unresolved, so that // VS can be aware of this version mismatch error and automatically do restore skipLockFileValidation = skipLockFileValidation && (_lockFile.Version == Constants.LockFileVersion); if (validLockFile || skipLockFileValidation) { NuGetDependencyProvider.ApplyLockFile(_lockFile); DependencyWalker = new DependencyWalker(new IDependencyProvider[] { ProjectDependencyProvider, NuGetDependencyProvider, referenceAssemblyDependencyResolver, gacDependencyResolver, unresolvedDependencyProvider }); } } if ((!validLockFile && !skipLockFileValidation) || !lockFileExists) { // We don't add NuGetDependencyProvider to DependencyWalker // It will leave all NuGet packages unresolved and give error message asking users to run "dnu restore" DependencyWalker = new DependencyWalker(new IDependencyProvider[] { ProjectDependencyProvider, referenceAssemblyDependencyResolver, gacDependencyResolver, unresolvedDependencyProvider }); } LibraryManager = new LibraryManager(() => DependencyWalker.Libraries); AssemblyLoadContextFactory = loadContextFactory ?? new RuntimeLoadContextFactory(ServiceProvider); // Create a new Application Environment for running the app. It needs a reference to the Host's application environment // (if any), which we can get from the service provider we were given. // If this is null (i.e. there is no Host Application Environment), that's OK, the Application Environment we are creating // will just have it's own independent set of global data. IApplicationEnvironment hostEnvironment = null; if (hostServices != null) { hostEnvironment = (IApplicationEnvironment)hostServices.GetService(typeof(IApplicationEnvironment)); } ApplicationEnvironment = new ApplicationEnvironment(Project, targetFramework, configuration, hostEnvironment); // Default services _serviceProvider.Add(typeof(IApplicationEnvironment), ApplicationEnvironment); _serviceProvider.Add(typeof(ILibraryManager), LibraryManager); _serviceProvider.Add(typeof(ICompilerOptionsProvider), new CompilerOptionsProvider(ProjectResolver)); // Not exposed to the application layer _serviceProvider.Add(typeof(IProjectResolver), ProjectResolver, includeInManifest: false); _serviceProvider.Add(typeof(NuGetDependencyResolver), NuGetDependencyProvider, includeInManifest: false); _serviceProvider.Add(typeof(ProjectReferenceDependencyProvider), ProjectDependencyProvider, includeInManifest: false); _serviceProvider.Add(typeof(IAssemblyLoadContextFactory), AssemblyLoadContextFactory, includeInManifest: false); }
public static void Initialize(ApplicationHostContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } context.ProjectDirectory = context.Project?.ProjectDirectory ?? context.ProjectDirectory; context.RootDirectory = context.RootDirectory ?? ProjectResolver.ResolveRootDirectory(context.ProjectDirectory); var projectResolver = new ProjectResolver(context.ProjectDirectory, context.RootDirectory); var frameworkReferenceResolver = context.FrameworkResolver ?? new FrameworkReferenceResolver(); context.PackagesDirectory = context.PackagesDirectory ?? PackageDependencyProvider.ResolveRepositoryPath(context.RootDirectory); var referenceAssemblyDependencyResolver = new ReferenceAssemblyDependencyResolver(frameworkReferenceResolver); var gacDependencyResolver = new GacDependencyResolver(); var projectDependencyProvider = new ProjectReferenceDependencyProvider(projectResolver); var unresolvedDependencyProvider = new UnresolvedDependencyProvider(); IList <IDependencyProvider> dependencyProviders = null; LockFileLookup lockFileLookup = null; if (context.Project == null) { Project project; if (Project.TryGetProject(context.ProjectDirectory, out project)) { context.Project = project; } else { throw new InvalidOperationException($"Unable to resolve project from {context.ProjectDirectory}"); } } var projectLockJsonPath = Path.Combine(context.ProjectDirectory, LockFileReader.LockFileName); var lockFileExists = File.Exists(projectLockJsonPath); var validLockFile = false; var skipLockFileValidation = context.SkipLockfileValidation; string lockFileValidationMessage = null; if (lockFileExists) { var lockFileReader = new LockFileReader(); var lockFile = lockFileReader.Read(projectLockJsonPath); validLockFile = lockFile.IsValidForProject(context.Project, out lockFileValidationMessage); // When the only invalid part of a lock file is version number, // we shouldn't skip lock file validation because we want to leave all dependencies unresolved, so that // VS can be aware of this version mismatch error and automatically do restore skipLockFileValidation = context.SkipLockfileValidation && (lockFile.Version == Constants.LockFileVersion); if (validLockFile || skipLockFileValidation) { lockFileLookup = new LockFileLookup(lockFile); var packageDependencyProvider = new PackageDependencyProvider(context.PackagesDirectory, lockFileLookup); dependencyProviders = new IDependencyProvider[] { projectDependencyProvider, packageDependencyProvider, referenceAssemblyDependencyResolver, gacDependencyResolver, unresolvedDependencyProvider }; } } if ((!validLockFile && !skipLockFileValidation) || !lockFileExists) { // We don't add the PackageDependencyProvider to DependencyWalker // It will leave all NuGet packages unresolved and give error message asking users to run "dnu restore" dependencyProviders = new IDependencyProvider[] { projectDependencyProvider, referenceAssemblyDependencyResolver, gacDependencyResolver, unresolvedDependencyProvider }; } var libraries = DependencyWalker.Walk(dependencyProviders, context.Project.Name, context.Project.Version, context.TargetFramework); context.LibraryManager = new LibraryManager(context.Project.ProjectFilePath, context.TargetFramework, libraries); if (!validLockFile) { context.LibraryManager.AddGlobalDiagnostics(new DiagnosticMessage( $"{lockFileValidationMessage}. Please run \"dnu restore\" to generate a new lock file.", Path.Combine(context.Project.ProjectDirectory, LockFileReader.LockFileName), DiagnosticMessageSeverity.Error)); } if (!lockFileExists) { context.LibraryManager.AddGlobalDiagnostics(new DiagnosticMessage( $"The expected lock file doesn't exist. Please run \"dnu restore\" to generate a new lock file.", Path.Combine(context.Project.ProjectDirectory, LockFileReader.LockFileName), DiagnosticMessageSeverity.Error)); } // Clear all the temporary memory aggressively here if we don't care about reuse // e.g. runtime scenarios lockFileLookup?.Clear(); projectResolver.Clear(); }
private static Result InitializeCore(ApplicationHostContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } context.ProjectDirectory = context.Project?.ProjectDirectory ?? context.ProjectDirectory; context.RootDirectory = context.RootDirectory ?? ProjectRootResolver.ResolveRootDirectory(context.ProjectDirectory); context.PackagesDirectory = context.PackagesDirectory ?? PackageDependencyProvider.ResolveRepositoryPath(context.RootDirectory); LockFileLookup lockFileLookup = null; if (context.Project == null) { Project project; if (Project.TryGetProject(context.ProjectDirectory, out project)) { context.Project = project; } else { throw new InvalidOperationException($"Unable to resolve project from {context.ProjectDirectory}"); } } var projectLockJsonPath = Path.Combine(context.ProjectDirectory, LockFileReader.LockFileName); if (context.LockFile == null && File.Exists(projectLockJsonPath)) { var lockFileReader = new LockFileReader(); context.LockFile = lockFileReader.Read(projectLockJsonPath); } var validLockFile = true; string lockFileValidationMessage = null; if (context.LockFile != null) { validLockFile = (context.LockFile.Version == Constants.LockFileVersion) && context.LockFile.IsValidForProject(context.Project, out lockFileValidationMessage); lockFileLookup = new LockFileLookup(context.LockFile); } var libraries = new List <LibraryDescription>(); var packageResolver = new PackageDependencyProvider(context.PackagesDirectory); var projectResolver = new ProjectDependencyProvider(); context.MainProject = projectResolver.GetDescription(context.TargetFramework, context.Project); // Add the main project libraries.Add(context.MainProject); if (lockFileLookup != null) { var target = SelectTarget(context, context.LockFile); if (target != null) { if (Logger.IsEnabled && string.IsNullOrEmpty(target.RuntimeIdentifier)) { // REVIEW(anurse): Is there ever a reason we want to use the RID-less target now? Logger.TraceWarning($"[{nameof(ApplicationHostContext)}] Lock File Target is Runtime-agnostic! This is generally not good."); } Logger.TraceInformation($"[{nameof(ApplicationHostContext)}] Using Lock File Target: {target.TargetFramework}/{target.RuntimeIdentifier}"); foreach (var library in target.Libraries) { if (string.Equals(library.Type, "project")) { var projectLibrary = lockFileLookup.GetProject(library.Name); var path = Path.GetFullPath(Path.Combine(context.ProjectDirectory, projectLibrary.Path)); var projectDescription = projectResolver.GetDescription(library.Name, path, library); libraries.Add(projectDescription); } else { var packageEntry = lockFileLookup.GetPackage(library.Name, library.Version); var packageDescription = packageResolver.GetDescription(packageEntry, library); libraries.Add(packageDescription); } } } } lockFileLookup?.Clear(); var lockFilePresent = context.LockFile != null; context.LockFile = null; // LockFile is no longer needed return(new Result(libraries, lockFilePresent, validLockFile, lockFileValidationMessage)); }