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);
}
}
}