<PackageReference Include="Castle.Core" Version="4.1.0" />

ModuleScope

public class ModuleScope
using Castle.Core.Internal; using Castle.DynamicProxy.Generators; using Castle.DynamicProxy.Serialization; using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Resources; namespace Castle.DynamicProxy { public class ModuleScope { public static readonly string DEFAULT_FILE_NAME = "CastleDynProxy2.dll"; public static readonly string DEFAULT_ASSEMBLY_NAME = "DynamicProxyGenAssembly2"; private ModuleBuilder moduleBuilderWithStrongName; private ModuleBuilder moduleBuilder; private readonly string strongAssemblyName; private readonly string weakAssemblyName; private readonly string strongModulePath; private readonly string weakModulePath; private readonly Dictionary<CacheKey, Type> typeCache = new Dictionary<CacheKey, Type>(); private readonly Lock cacheLock = Lock.Create(); private readonly object moduleLocker = new object(); private readonly bool savePhysicalAssembly; private readonly bool disableSignedModule; private readonly INamingScope namingScope; public INamingScope NamingScope => namingScope; public Lock Lock => cacheLock; public ModuleBuilder StrongNamedModule => moduleBuilderWithStrongName; public string StrongNamedModuleName => Path.GetFileName(strongModulePath); public string StrongNamedModuleDirectory { get { string directoryName = Path.GetDirectoryName(strongModulePath); if (string.IsNullOrEmpty(directoryName)) return null; return directoryName; } } public ModuleBuilder WeakNamedModule => moduleBuilder; public string WeakNamedModuleName => Path.GetFileName(weakModulePath); public string WeakNamedModuleDirectory { get { string directoryName = Path.GetDirectoryName(weakModulePath); if (directoryName == string.Empty) return null; return directoryName; } } public ModuleScope() : this(false, false) { } public ModuleScope(bool savePhysicalAssembly) : this(savePhysicalAssembly, false) { } public ModuleScope(bool savePhysicalAssembly, bool disableSignedModule) : this(savePhysicalAssembly, disableSignedModule, DEFAULT_ASSEMBLY_NAME, DEFAULT_FILE_NAME, DEFAULT_ASSEMBLY_NAME, DEFAULT_FILE_NAME) { } public ModuleScope(bool savePhysicalAssembly, bool disableSignedModule, string strongAssemblyName, string strongModulePath, string weakAssemblyName, string weakModulePath) : this(savePhysicalAssembly, disableSignedModule, new NamingScope(), strongAssemblyName, strongModulePath, weakAssemblyName, weakModulePath) { } public ModuleScope(bool savePhysicalAssembly, bool disableSignedModule, INamingScope namingScope, string strongAssemblyName, string strongModulePath, string weakAssemblyName, string weakModulePath) { this.savePhysicalAssembly = savePhysicalAssembly; this.disableSignedModule = disableSignedModule; this.namingScope = namingScope; this.strongAssemblyName = strongAssemblyName; this.strongModulePath = strongModulePath; this.weakAssemblyName = weakAssemblyName; this.weakModulePath = weakModulePath; } public Type GetFromCache(CacheKey key) { typeCache.TryGetValue(key, out Type value); return value; } public void RegisterInCache(CacheKey key, Type type) { typeCache[key] = type; } public static byte[] GetKeyPair() { using (Stream stream = IntrospectionExtensions.GetTypeInfo(typeof(ModuleScope)).Assembly.GetManifestResourceStream("Castle.DynamicProxy.DynProxy.snk")) { if (stream == null) throw new MissingManifestResourceException("Should have a Castle.DynamicProxy.DynProxy.snk as an embedded resource, so Dynamic Proxy could sign generated assembly"); int num = (int)stream.Length; byte[] array = new byte[num]; stream.Read(array, 0, num); return array; } } public ModuleBuilder ObtainDynamicModule(bool isStrongNamed) { if (isStrongNamed) return ObtainDynamicModuleWithStrongName(); return ObtainDynamicModuleWithWeakName(); } public ModuleBuilder ObtainDynamicModuleWithStrongName() { if (disableSignedModule) throw new InvalidOperationException("Usage of signed module has been disabled. Use unsigned module or enable signed module."); lock (moduleLocker) { if ((Module)moduleBuilderWithStrongName == (Module)null) moduleBuilderWithStrongName = CreateModule(true); return moduleBuilderWithStrongName; } } public ModuleBuilder ObtainDynamicModuleWithWeakName() { lock (moduleLocker) { if ((Module)moduleBuilder == (Module)null) moduleBuilder = CreateModule(false); return moduleBuilder; } } private ModuleBuilder CreateModule(bool signStrongName) { AssemblyName assemblyName = GetAssemblyName(signStrongName); string text = signStrongName ? StrongNamedModuleName : WeakNamedModuleName; if (savePhysicalAssembly) { AssemblyBuilder assemblyBuilder; try { assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, (AssemblyBuilderAccess)3, signStrongName ? StrongNamedModuleDirectory : WeakNamedModuleDirectory); } catch (ArgumentException ex) { if (!signStrongName && !ex.StackTrace.Contains("ComputePublicKey")) throw; throw new ArgumentException($"""{GetType()}""", ex); } return assemblyBuilder.DefineDynamicModule(text, text, false); } return AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run).DefineDynamicModule(text); } private AssemblyName GetAssemblyName(bool signStrongName) { AssemblyName assemblyName = new AssemblyName { Name = (signStrongName ? strongAssemblyName : weakAssemblyName) }; if (signStrongName) { byte[] keyPair = GetKeyPair(); if (keyPair != null) assemblyName.KeyPair = new StrongNameKeyPair(keyPair); } return assemblyName; } public string SaveAssembly() { if (!savePhysicalAssembly) return null; if ((Module)StrongNamedModule != (Module)null && (Module)WeakNamedModule != (Module)null) throw new InvalidOperationException("Both a strong-named and a weak-named assembly have been generated."); if ((Module)StrongNamedModule != (Module)null) return SaveAssembly(true); if ((Module)WeakNamedModule != (Module)null) return SaveAssembly(false); return null; } public string SaveAssembly(bool strongNamed) { if (!savePhysicalAssembly) return null; AssemblyBuilder assemblyBuilder; string text; string fullyQualifiedName; if (strongNamed) { if ((Module)StrongNamedModule == (Module)null) throw new InvalidOperationException("No strong-named assembly has been generated."); assemblyBuilder = (AssemblyBuilder)StrongNamedModule.Assembly; text = StrongNamedModuleName; fullyQualifiedName = StrongNamedModule.FullyQualifiedName; } else { if ((Module)WeakNamedModule == (Module)null) throw new InvalidOperationException("No weak-named assembly has been generated."); assemblyBuilder = (AssemblyBuilder)WeakNamedModule.Assembly; text = WeakNamedModuleName; fullyQualifiedName = WeakNamedModule.FullyQualifiedName; } if (File.Exists(fullyQualifiedName)) File.Delete(fullyQualifiedName); AddCacheMappings(assemblyBuilder); assemblyBuilder.Save(text); return fullyQualifiedName; } private void AddCacheMappings(AssemblyBuilder builder) { Dictionary<CacheKey, string> dictionary = default(Dictionary<CacheKey, string>); using (Lock.ForReading()) { dictionary = new Dictionary<CacheKey, string>(); foreach (KeyValuePair<CacheKey, Type> item in typeCache) { if (builder.Equals(item.Value.Assembly)) dictionary.Add(item.Key, item.Value.FullName); } } CacheMappingsAttribute.ApplyTo(builder, dictionary); } public void LoadAssemblyIntoCache(Assembly assembly) { if (assembly == (Assembly)null) throw new ArgumentNullException("assembly"); CacheMappingsAttribute[] obj = (CacheMappingsAttribute[])assembly.GetCustomAttributes(typeof(CacheMappingsAttribute), false); if (obj.Length == 0) throw new ArgumentException($"""{assembly.FullName}""", "assembly"); foreach (KeyValuePair<CacheKey, string> deserializedMapping in obj[0].GetDeserializedMappings()) { Type type = assembly.GetType(deserializedMapping.Value); if (type != (Type)null) RegisterInCache(deserializedMapping.Key, type); } } public TypeBuilder DefineType(bool inSignedModulePreferably, string name, TypeAttributes flags) { return ObtainDynamicModule(!disableSignedModule & inSignedModulePreferably).DefineType(name, flags); } } }