in src/dotnet/AspirePlugin/ProjectModel/AspireProjectModelService.cs [26:168]
public class AspireProjectModelService(ISolution solution, ILogger logger)
{
/// <summary>
/// References multiple projects from an Aspire Host project.
/// </summary>
/// <param name="hostProjectFilePath">The file path of the Aspire Host project which will reference other projects.</param>
/// <param name="projectFilePaths">A list of file paths for the projects to be referenced in the host project.</param>
/// <param name="lifetime">The <see cref="Lifetime"/> object controlling the scope of the operation, allowing cancellation if needed.</param>
public ReferenceProjectsFromAppHostResponse? ReferenceProjectsFromAppHost(
VirtualFileSystemPath hostProjectFilePath,
List<VirtualFileSystemPath> projectFilePaths,
Lifetime lifetime)
{
var solutionHost = solution.ProjectsHostContainer().GetComponent<ISolutionHost>();
solutionHost.SuspendAsyncProjectsReloading(lifetime);
var hostProject = solution.FindProjectByPath(hostProjectFilePath);
if (hostProject is null)
{
logger.Warn("Unable to find a Host project");
return null;
}
var referencedProjectPaths = new List<VirtualFileSystemPath>(projectFilePaths.Count);
foreach (var projectPath in projectFilePaths)
{
var project = AddProjectReference(hostProject, projectPath);
if (project is null)
{
continue;
}
referencedProjectPaths.Add(projectPath);
lifetime.ThrowIfNotAlive();
}
var resultPaths = referencedProjectPaths.Select(it => it.ToRd()).ToList();
return new ReferenceProjectsFromAppHostResponse(resultPaths);
}
/// <summary>
/// References an Aspire Shared project from specified projects.
/// </summary>
/// <param name="sharedProjectFilePath">The file path of the Aspire Shared project to be referenced in other projects.</param>
/// <param name="projectFilePaths">A list of file paths for the projects which will reference the shared project.</param>
/// <param name="lifetime">The <see cref="Lifetime"/> object controlling the scope of the operation, allowing cancellation if needed.</param>
public ReferenceServiceDefaultsFromProjectsResponse? ReferenceServiceDefaultsFromProjects(
VirtualFileSystemPath sharedProjectFilePath,
List<VirtualFileSystemPath> projectFilePaths,
Lifetime lifetime)
{
var solutionHost = solution.ProjectsHostContainer().GetComponent<ISolutionHost>();
solutionHost.SuspendAsyncProjectsReloading(lifetime);
var sharedProject = solution.FindProjectByPath(sharedProjectFilePath);
if (sharedProject is null)
{
logger.Warn("Unable to find a Shared project");
return null;
}
var projectPathsWithReference = new List<VirtualFileSystemPath>(projectFilePaths.Count);
foreach (var projectPath in projectFilePaths)
{
var project = AddProjectReference(projectPath, sharedProject);
if (project is null)
{
continue;
}
projectPathsWithReference.Add(projectPath);
lifetime.ThrowIfNotAlive();
}
var resultPaths = projectPathsWithReference.Select(it => it.ToRd()).ToList();
return new ReferenceServiceDefaultsFromProjectsResponse(resultPaths);
}
private IProject? AddProjectReference(IProject targetProject, VirtualFileSystemPath projectToReference)
{
using (solution.Locks.UsingReadLock())
{
var toProject = solution.FindProjectByProjectFilePath(projectToReference);
if (toProject is null)
{
logger.Warn("Unable to resolve project from a file path");
return null;
}
AddProjectReference(targetProject, toProject);
return toProject;
}
}
private IProject? AddProjectReference(VirtualFileSystemPath targetProject, IProject projectToReference)
{
using (solution.Locks.UsingReadLock())
{
var fromProject = solution.FindProjectByProjectFilePath(targetProject);
if (fromProject is null)
{
logger.Warn("Unable to resolve project from a file path");
return null;
}
AddProjectReference(fromProject, projectToReference);
return fromProject;
}
}
private void AddProjectReference(IProject targetProject, IProject projectToReference)
{
var existingReferences = new Dictionary<TargetFrameworkId, List<Guid>>(targetProject.TargetFrameworkIds.Count);
foreach (var tfm in targetProject.TargetFrameworkIds)
{
if (tfm is null) continue;
var references = targetProject.GetProjectReferences(tfm);
existingReferences[tfm] = references
.SelectNotNull(it =>
{
if (it is GuidProjectReference gpr)
return (Guid?)gpr.ReferencedProjectGuid;
else
return null;
}).ToList();
}
solution.InvokeUnderTransaction(cookie =>
{
foreach (var tfm in targetProject.TargetFrameworkIds)
{
if (existingReferences[tfm].Contains(projectToReference.Guid))
{
continue;
}
cookie.AddModuleReference(targetProject, projectToReference, tfm);
}
});
}
}