Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 12 additions & 35 deletions src/RoslynTestKit/Helpers/AdhocWorkspace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,17 @@ namespace RoslynTestKit
public sealed class AdhocWorkspace : Workspace
{
#if NET8_0_OR_GREATER
private static readonly object _reflectionLock = new object();
private static (MethodInfo Method, ParameterInfo[] Parameters)? _cachedCreateMethodInfo;
private static readonly Lazy<(MethodInfo Method, ParameterInfo[] Parameters)> _projectInfoCreateMethod =
new(() =>
{
var createMethod = typeof(ProjectInfo)
.GetMethods(BindingFlags.Public | BindingFlags.Static)
.FirstOrDefault(m => m.Name == "Create")
?? throw new InvalidOperationException(
"Could not find ProjectInfo.Create method. Ensure Microsoft.Dynamics.Nav.CodeAnalysis.Workspaces is referenced.");

return (createMethod, createMethod.GetParameters());
}, LazyThreadSafetyMode.PublicationOnly);
#endif

public AdhocWorkspace(HostServices host, string workspaceKind = "Custom")
Expand Down Expand Up @@ -95,7 +104,7 @@ public Solution AddSolution(SolutionInfo solutionInfo)
/// </remarks>
private static ProjectInfo CreateProjectInfoViaReflection(string name, string language)
{
var (method, parameters) = GetCachedCreateMethod();
var (method, parameters) = _projectInfoCreateMethod.Value;
var args = BuildMethodArguments(parameters, name, language);

var result = method.Invoke(null, args);
Expand All @@ -107,38 +116,6 @@ private static ProjectInfo CreateProjectInfoViaReflection(string name, string la
return projectInfo;
}

/// <summary>
/// Gets the cached MethodInfo and ParameterInfo for ProjectInfo.Create, initializing if necessary.
/// Thread-safe using double-checked locking pattern.
/// </summary>
private static (MethodInfo Method, ParameterInfo[] Parameters) GetCachedCreateMethod()
{
var cached = _cachedCreateMethodInfo;
if (cached != null)
{
return cached.Value;
}

lock (_reflectionLock)
{
cached = _cachedCreateMethodInfo;
if (cached != null)
{
return cached.Value;
}

var createMethod = typeof(ProjectInfo)
.GetMethods(BindingFlags.Public | BindingFlags.Static)
.FirstOrDefault(m => m.Name == "Create")
?? throw new InvalidOperationException(
"Could not find ProjectInfo.Create method. Ensure Microsoft.Dynamics.Nav.CodeAnalysis.Workspaces is referenced.");

var result = (createMethod, createMethod.GetParameters());
_cachedCreateMethodInfo = result;
return result;
}
}

/// <summary>
/// Builds the argument array for calling ProjectInfo.Create via reflection.
/// </summary>
Expand Down
Loading