Aetheria/Assets/Scripts/NIH/MagicOnion/Utils/DynamicAssembly.cs
hyperion51 c58ba0b1da Copy Aetheria Code
Added a bunch of code from the old Aetheria project
2020-02-27 18:51:07 +00:00

98 lines
No EOL
3 KiB
C#

#if NON_UNITY || !NET_STANDARD_2_0
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
namespace MagicOnion.Utils
{
#if ENABLE_SAVE_ASSEMBLY
public
#else
internal
#endif
class DynamicAssembly
{
readonly object gate = new object();
#if ENABLE_SAVE_ASSEMBLY
readonly string moduleName;
#endif
readonly AssemblyBuilder assemblyBuilder;
readonly ModuleBuilder moduleBuilder;
// don't expose ModuleBuilder(should use lock)
// public ModuleBuilder ModuleBuilder { get { return moduleBuilder; } }
public DynamicAssembly(string moduleName)
{
#if ENABLE_SAVE_ASSEMBLY
this.moduleName = moduleName;
this.assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(moduleName), AssemblyBuilderAccess.RunAndSave);
this.moduleBuilder = assemblyBuilder.DefineDynamicModule(moduleName, moduleName + ".dll");
#else
this.assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(moduleName), AssemblyBuilderAccess.Run);
this.moduleBuilder = assemblyBuilder.DefineDynamicModule(moduleName);
#endif
// HACK: Allow access to `internal` classes from dynamically generated assembly.
// https://www.strathweb.com/2018/10/no-internalvisibleto-no-problem-bypassing-c-visibility-rules-with-roslyn/
var ignoreAccessChecksTo = new CustomAttributeBuilder(typeof(IgnoresAccessChecksToAttribute).GetConstructor(new[] {typeof(string)}), new []{ "MagicOnion" });
this.assemblyBuilder.SetCustomAttribute(ignoreAccessChecksTo);
}
// requires lock on mono environment(for example, UnityEditor). see: https://github.com/neuecc/MessagePack-CSharp/issues/161
public TypeBuilder DefineType(string name, TypeAttributes attr)
{
lock (gate)
{
return moduleBuilder.DefineType(name, attr);
}
}
public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent)
{
lock (gate)
{
return moduleBuilder.DefineType(name, attr, parent);
}
}
public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, Type[] interfaces)
{
lock (gate)
{
return moduleBuilder.DefineType(name, attr, parent, interfaces);
}
}
#if ENABLE_SAVE_ASSEMBLY
public AssemblyBuilder Save()
{
assemblyBuilder.Save(moduleName + ".dll");
return assemblyBuilder;
}
#endif
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
AssemblyName = assemblyName;
}
public string AssemblyName { get; }
}
}
#endif