in src/Microsoft.NET.Sdk.Functions.Generator/FunctionJsonConverter.cs [170:257]
private bool TryGenerateFunctionJsons()
{
var loadContext = new AssemblyLoadContext(Path.GetFileName(_assemblyPath), isCollectible: true);
var assemblyRoot = Path.GetDirectoryName(_assemblyPath);
var resolver = new DefaultAssemblyResolver();
resolver.AddSearchDirectory(assemblyRoot);
var readerParams = new ReaderParameters
{
AssemblyResolver = resolver
};
loadContext.Resolving += ResolveAssembly;
bool ret;
using (var scope = loadContext.EnterContextualReflection())
{
var module = ModuleDefinition.ReadModule(_assemblyPath, readerParams);
IEnumerable<TypeDefinition> exportedTypes = module.Types;
if (_functionsInDependencies)
{
foreach (var referencedAssembly in module.AssemblyReferences)
{
var tryPath = Path.Combine(assemblyRoot, $"{referencedAssembly.Name}.dll");
if (File.Exists(tryPath))
{
try
{
var loadedModule = ModuleDefinition.ReadModule(tryPath, readerParams);
exportedTypes = exportedTypes.Concat(loadedModule.Types);
}
catch (Exception ex)
{
_logger.LogWarning($"Could not evaluate '{referencedAssembly.Name}' for function types. Exception message: {ex.Message}");
}
}
}
}
var functions = GenerateFunctions(exportedTypes).ToList();
foreach (var function in functions.Where(f => f.HasValue && !f.Value.outputFile.Exists).Select(f => f.Value))
{
function.schema.Serialize(function.outputFile.FullName);
}
ret = functions.All(f => f.HasValue);
}
loadContext.Unload();
return ret;
Assembly ResolveAssembly(AssemblyLoadContext context, AssemblyName assemblyName)
{
Assembly result = null;
// First, check the assembly root dir. Assemblies copied with the app always wins.
var path = Path.Combine(assemblyRoot, assemblyName.Name + ".dll");
if (File.Exists(path))
{
result = context.LoadFromAssemblyPath(path);
if (result != null)
{
return result;
}
}
// Then, check if the assembly is already loaded into the default context.
// This is typically the case for framework assemblies like System.Private.Corelib.dll.
if (AssemblyLoadContext.Default.Assemblies.FirstOrDefault(a => a.GetName().Equals(assemblyName)) is Assembly existing)
{
return existing;
}
// Lastly, try the resolution logic used by cecil. This can produce assemblies with
// different versions, which may cause issues. But not doing this fails in more cases.
var resolved = resolver.Resolve(AssemblyNameReference.Parse(assemblyName.FullName));
path = resolved?.MainModule.FileName;
if (path != null)
{
result = context.LoadFromAssemblyPath(path);
}
return result;
}
}