Files
sbox-public/engine/Sandbox.Access/AccessControl.Resolve.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

85 lines
2.5 KiB
C#

using Mono.Cecil;
using System;
using System.Collections.Concurrent;
namespace Sandbox;
public partial class AccessControl
{
static ConcurrentDictionary<AssemblyNameReference, AssemblyDefinition> GlobalAssemblyCache = new( AssemblyNameComparer.Instance );
public AssemblyDefinition Resolve( AssemblyNameReference name )
{
//
// Look in the dynamic assemblies first
//
if ( Assemblies != null )
{
if ( Assemblies.TryGetValue( name, out var assm ) )
return assm;
var newestNameMatch = Assemblies
.Where( x => x.Key.Name.Equals( name.Name, StringComparison.OrdinalIgnoreCase ) )
//.Where( x => x.Key.Version.CompareTo( name.Version ) >= 0 )
.OrderByDescending( x => x.Key.Version )
.FirstOrDefault();
if ( newestNameMatch.Value != null )
return newestNameMatch.Value;
}
//
// We only resolve certain named dlls from disk - and certainly not package.
//
if ( !name.Name.StartsWith( "Sandbox.", StringComparison.OrdinalIgnoreCase ) &&
!name.Name.StartsWith( "System.", StringComparison.OrdinalIgnoreCase ) &&
name.Name != "Microsoft.AspNetCore.Components" )
throw NotResolved( name );
//
// Now look at our System. and Sandbox. assemblies
//
if ( GlobalAssemblyCache.TryGetValue( name, out var systemAssembly ) )
return systemAssembly;
lock ( GlobalAssemblyCache )
{
return GlobalAssemblyCache.GetOrAdd( name, FindAssemblyOnDisk );
}
}
AssemblyDefinition FindAssemblyOnDisk( AssemblyNameReference name )
{
var dllName = $"{name.Name}.dll";
var corePath = System.IO.Path.GetDirectoryName( typeof( Object ).Assembly.Location );
var testPath = System.IO.Path.Combine( corePath, dllName );
if ( !System.IO.File.Exists( testPath ) )
{
var gamePath = System.IO.Path.GetDirectoryName( GetType().Assembly.Location );
testPath = System.IO.Path.Combine( gamePath, dllName );
}
if ( !System.IO.File.Exists( testPath ) )
throw NotResolved( name );
var fileContent = System.IO.File.ReadAllBytes( testPath );
var stream = new MemoryStream( fileContent );
var options = new ReaderParameters { ReadingMode = ReadingMode.Immediate, InMemory = true, AssemblyResolver = this };
var assm = AssemblyDefinition.ReadAssembly( stream, options );
return assm;
}
private Exception NotResolved( AssemblyNameReference name )
{
return new System.Exception( $"Couldn't resolve '{name}' [{string.Join( ";", Assemblies.Select( x => $"{x.Key}@{x.Key}" ) )}]" );
}
public AssemblyDefinition Resolve( AssemblyNameReference name, ReaderParameters parameters )
{
return Resolve( name );
}
}