Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

将元数据管理移到LoadContext 中进行 #261

Merged
merged 1 commit into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ static AmbiguityUsings()
{
SemanticAction = (builder, compilation, ignoreAccessibility) =>
{
builder.CheckNullLoadContext();

var trees = compilation.SyntaxTrees;
foreach (var tree in trees)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ public CSharpCompilation GetAvailableCompilation(Func<CSharpCompilationOptions,
//{
// _compilerOptions.WithLowerVersionsAssembly();
//}
this.CheckNullLoadContext();
var options = _compilerOptions.GetCompilationOptions(_codeOptimizationLevel, _withDebugInfo);
if (initOptionsFunc != null)
{
Expand All @@ -123,7 +122,7 @@ public CSharpCompilation GetAvailableCompilation(Func<CSharpCompilationOptions,
}
else if (_combineReferenceBehavior == CombineReferenceBehavior.UseCurrent)
{
references = LoadContext!.References.GetReferences();
references = LoadContext!.ReferenceRecorder.GetReferences();
}
else
{
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using Natasha.DynamicLoad.Base;
using System;
using System.Runtime.CompilerServices;

/// <summary>
/// 程序集编译构建器 - 域
/// </summary>
public sealed partial class AssemblyCSharpBuilder
{
private NatashaLoadContext _loadContext;
private readonly DomainConfiguration _domainConfiguration;

/// <summary>
/// 配置上下文
/// </summary>
/// <param name="handle"></param>
/// <returns></returns>
public AssemblyCSharpBuilder ConfigLoadContext(Func<NatashaLoadContext, NatashaLoadContext> handle)
{
_loadContext = handle(_loadContext);
return this;
}

/// <summary>
/// 编译单元所在的上下文
/// </summary>
public NatashaLoadContext LoadContext
{
get
{
return _loadContext;
}
set
{
_loadContext = value;
}
}
/// <summary>
/// 编译单元所在域.该域实现了 INatashaDynamicLoadContextBase 接口,并由 INatashaDynamicLoadContextCreator 接口实现创建而来
/// </summary>
public INatashaDynamicLoadContextBase Domain
{
get { return _loadContext.Domain; }
}

/// <summary>
/// 配置域
/// </summary>
/// <param name="action"></param>
/// <returns></returns>
public AssemblyCSharpBuilder ConfigDomain(Action<DomainConfiguration> action)
{
action(_domainConfiguration);
if (Domain.Name != "Default")
{
Domain.SetAssemblyLoadBehavior(_domainConfiguration._dependencyLoadBehavior);
}
return this;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -136,17 +136,14 @@ public AssemblyCSharpBuilder Add(string script, UsingLoadBehavior usingLoadBehav
switch (usingLoadBehavior)
{
case UsingLoadBehavior.WithDefault:
this.CheckNullLoadContext();
return AddScript(NatashaLoadContext.DefaultContext.UsingRecorder + script);
case UsingLoadBehavior.WithCurrent:
this.CheckNullLoadContext();
if (Domain!.Name == NatashaLoadContext.DefaultName)
{
return AddScript(NatashaLoadContext.DefaultContext.UsingRecorder + script);
}
return AddScript(LoadContext!.UsingRecorder + script);
case UsingLoadBehavior.WithAll:
this.CheckNullLoadContext();
if (Domain!.Name == NatashaLoadContext.DefaultName)
{
return AddScript(NatashaLoadContext.DefaultContext.UsingRecorder + script);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ public AssemblyCSharpBuilder(string assemblyName)
_domainConfiguration = new DomainConfiguration();
_semanticAnalysistor = [UsingAnalysistor._usingSemanticDelegate];
_specifiedReferences = [];
_loadContext = NatashaLoadContext.DefaultContext;
if (_loadContext == default!)
{
throw new NullReferenceException("LoadContext 为空!请检查是否调用 NatashaManagement.Preheating 或 NatashaManagement.RegistDomainCreator, 若调用,请检查 Builder 是否创建了域!");
}
}

internal static bool HasInitialized;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ internal NatashaLoadContext(string key)
public static INatashaDynamicLoadContextCreator Creator = default!;
public const string DefaultName = "Default";

public static void SetLoadContextCreator<TCreator>() where TCreator : INatashaDynamicLoadContextCreator, new()
internal static void SetLoadContextCreator<TCreator>() where TCreator : INatashaDynamicLoadContextCreator, new()
{
Creator = new TCreator();
DefaultContext = new NatashaLoadContext();
Expand All @@ -44,18 +44,18 @@ public IEnumerable<MetadataReference> GetReferences(ReferenceConfiguration confi
{
if (Domain.Name == DefaultContext.Domain.Name)
{
return References.GetReferences();
return ReferenceRecorder.GetReferences();
}
else
{
return References.CombineWithDefaultReferences(DefaultContext.References, configuration._compileReferenceBehavior, configuration._referenceSameNamePickFunc);
return ReferenceRecorder.CombineWithDefaultReferences(DefaultContext.ReferenceRecorder, configuration._compileReferenceBehavior, configuration._referenceSameNamePickFunc);
}
}

/// <summary>
/// 引用 记录
/// </summary>
public readonly NatashaMetadataCache References = new();
public readonly NatashaMetadataCache ReferenceRecorder = new();
/// <summary>
/// Using 记录
/// </summary>
Expand All @@ -71,15 +71,83 @@ internal void LoadMetadataWithAssembly(Assembly assembly)
}


public void AddReferenceAndUsing(AssemblyName name, MetadataReference metadataReference, HashSet<string> usings, AssemblyCompareInfomation compareInfomation = AssemblyCompareInfomation.None)
public NatashaLoadContext AddReferenceAndUsing(AssemblyName name, MetadataReference metadataReference, HashSet<string> usings, AssemblyCompareInfomation compareInfomation = AssemblyCompareInfomation.None)
{
References.AddReference(name, metadataReference, compareInfomation);
ReferenceRecorder.AddReference(name, metadataReference, compareInfomation);
UsingRecorder.Using(usings);
return this;
}


/// <summary>
/// 根据 实现程序集, 增加元数据 和 using
/// </summary>
/// <param name="assembly">程序集</param>
/// <param name="excludeAssembliesFunc">过滤委托</param>
/// <param name="loadReferenceBehavior">加载行为</param>
public NatashaLoadContext AddReferenceAndUsingCode(Assembly assembly, Func<AssemblyName, bool>? excludeAssembliesFunc = null, AssemblyCompareInfomation loadReferenceBehavior = AssemblyCompareInfomation.None)
{
var result = MetadataHelper.GetMetadataAndNamespaceFromMemory(assembly, null);
if (result.HasValue)
{
AddReferenceAndUsing(result.Value.asmName, result.Value.metadata, result.Value.namespaces, loadReferenceBehavior);
var assmblies = Creator.GetDependencyAssemblies(assembly);
if (assmblies != null)
{
if (excludeAssembliesFunc != null)
{
foreach (var depAssembly in assmblies)
{
var asmName = depAssembly.GetName();
if (!ReferenceRecorder.HasReference(asmName) && !excludeAssembliesFunc(asmName))
{
result = MetadataHelper.GetMetadataAndNamespaceFromMemory(depAssembly, null);
if (result.HasValue)
{
AddReferenceAndUsing(asmName, result.Value.metadata, result.Value.namespaces, loadReferenceBehavior);
}
}
}
}
else
{
foreach (var depAssembly in assmblies)
{
var asmName = depAssembly.GetName();
if (!ReferenceRecorder.HasReference(asmName))
{
result = MetadataHelper.GetMetadataAndNamespaceFromMemory(depAssembly, null);
if (result.HasValue)
{
AddReferenceAndUsing(asmName, result.Value.metadata, result.Value.namespaces, loadReferenceBehavior);
}
}
}
}

}
}
return this;
}

/// <summary>
/// 根据 引用程序集所在的文件, 增加元数据 和 using
/// </summary>
/// <param name="path">文件路径</param>
/// <param name="loadReferenceBehavior">加载行为</param>
public NatashaLoadContext AddReferenceAndUsingCode(string path, AssemblyCompareInfomation loadReferenceBehavior = AssemblyCompareInfomation.None)
{
var result = MetadataHelper.GetMetadataAndNamespaceFromFile(path, null);
if (result.HasValue)
{
AddReferenceAndUsing(result.Value.asmName, result.Value.metadata, result.Value.namespaces, loadReferenceBehavior);
}
return this;
}

public void Dispose()
{
References.Dispose();
ReferenceRecorder.Dispose();
UsingRecorder.Dispose();
Domain.Dispose();
}
Expand Down
Loading
Loading