chore: initialize standalone UPM package
Publish UPM package / publish (push) Failing after 1s

This commit is contained in:
2026-08-26 02:50:18 +08:00
commit 1c921f5aec
86 changed files with 6934 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c297548ebc9165f448111a35488d368e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+529
View File
@@ -0,0 +1,529 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;
using Mono.Cecil.Pdb;
using Unity.CompilationPipeline.Common.Diagnostics;
using Unity.CompilationPipeline.Common.ILPostProcessing;
namespace ShrinkEventBus.CodeGen
{
public sealed class EventBusILPostProcessor : ILPostProcessor
{
private const string RuntimeAssemblyName = "ShrinkEventBus.Runtime";
public override ILPostProcessor GetInstance() => this;
public override bool WillProcess(ICompiledAssembly compiledAssembly)
{
if (!ReferencesAssembly(compiledAssembly, RuntimeAssemblyName))
return false;
return true;
}
public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly)
{
var diagnostics = new List<DiagnosticMessage>();
if (!WillProcess(compiledAssembly))
return new ILPostProcessResult(compiledAssembly.InMemoryAssembly, diagnostics);
var assemblyDefinition = AssemblyDefinitionFor(compiledAssembly);
var module = assemblyDefinition.MainModule;
try
{
var generatedSubscriberType = FindType(module, "ShrinkEventBus.ShrinkEventSubscriberAttribute", RuntimeAssemblyName);
var generatedSubscribeType = FindType(module, "ShrinkEventBus.ShrinkSubscribeAttribute", RuntimeAssemblyName);
if (generatedSubscriberType == null || generatedSubscribeType == null)
return GetResult(assemblyDefinition, diagnostics);
foreach (var type in GetAllTypes(module.Types)
.Where(type => !type.IsInterface && !type.IsAbstract)
.Where(type => HasAttribute(type, generatedSubscriberType))
.Where(type => type.Methods.Any(method =>
!method.IsStatic && HasAttribute(method, generatedSubscribeType))))
{
InjectGeneratedBinding(type, module, generatedSubscribeType);
}
var staticSubscriberTypes = GetAllTypes(module.Types)
.Where(type => HasAttribute(type, generatedSubscriberType))
.Where(type => type.Methods.Any(method =>
method.IsStatic && HasAttribute(method, generatedSubscribeType)))
.ToArray();
if (staticSubscriberTypes.Length > 0)
InjectStaticBootstrap(module, staticSubscriberTypes, generatedSubscribeType);
}
catch (Exception ex)
{
diagnostics.Add(new DiagnosticMessage
{
DiagnosticType = DiagnosticType.Error,
MessageData = $"[ShrinkEventBus.CodeGen] {ex.Message}"
});
}
return GetResult(assemblyDefinition, diagnostics);
}
private static bool ReferencesAssembly(ICompiledAssembly compiledAssembly, string assemblyName)
{
return compiledAssembly.References.Any(reference =>
string.Equals(Path.GetFileNameWithoutExtension(reference), assemblyName, StringComparison.Ordinal));
}
private static bool HasAttribute(ICustomAttributeProvider provider, TypeReference expectedAttributeType)
{
return provider.CustomAttributes.Any(attribute => attribute.AttributeType.FullName == expectedAttributeType.FullName);
}
private static IEnumerable<TypeDefinition> GetAllTypes(IEnumerable<TypeDefinition> roots)
{
foreach (var type in roots)
{
yield return type;
foreach (var nested in GetAllTypes(type.NestedTypes))
yield return nested;
}
}
private static void InjectGeneratedBinding(TypeDefinition type, ModuleDefinition module,
TypeReference subscribeAttributeType)
{
var generatedInterface = FindType(module,
"ShrinkEventBus.IShrinkGeneratedSubscriber", RuntimeAssemblyName)
?? throw new InvalidOperationException("IShrinkGeneratedSubscriber was not found.");
if (type.Interfaces.Any(item => item.InterfaceType.FullName == generatedInterface.FullName))
return;
var resolverType = FindType(module, "ShrinkEventBus.IShrinkBusResolver", RuntimeAssemblyName)
?? throw new InvalidOperationException("IShrinkBusResolver was not found.");
var busKeyType = FindType(module, "ShrinkEventBus.ShrinkBusKey", RuntimeAssemblyName)
?? throw new InvalidOperationException("ShrinkBusKey was not found.");
var bindingType = FindType(module, "ShrinkEventBus.ShrinkEventBinding", RuntimeAssemblyName)
?? throw new InvalidOperationException("ShrinkEventBinding was not found.");
var bindingHelperType = FindType(module, "ShrinkEventBus.ShrinkGeneratedBinding", RuntimeAssemblyName)
?? throw new InvalidOperationException("ShrinkGeneratedBinding was not found.");
var priorityType = FindType(module, "ShrinkEventBus.ShrinkEventPriority", RuntimeAssemblyName)
?? throw new InvalidOperationException("ShrinkEventPriority was not found.");
var asyncHandlerType = FindType(module, "ShrinkEventBus.ShrinkAsyncEventHandler`1", RuntimeAssemblyName)
?? throw new InvalidOperationException("ShrinkAsyncEventHandler was not found.");
var nullableBusKey = new GenericInstanceType(module.ImportReference(typeof(Nullable<>)));
nullableBusKey.GenericArguments.Add(busKeyType);
var disposableType = module.ImportReference(typeof(IDisposable));
var bindingDefinition = bindingType.Resolve()
?? throw new InvalidOperationException("ShrinkEventBinding could not be resolved.");
var bindingCtor = module.ImportReference(bindingDefinition.Methods.Single(method =>
method.IsConstructor && method.Parameters.Count == 0));
var bindingAdd = module.ImportReference(bindingDefinition.Methods.Single(method =>
method.Name == "Add" && method.Parameters.Count == 1));
var helperDefinition = bindingHelperType.Resolve()
?? throw new InvalidOperationException("ShrinkGeneratedBinding could not be resolved.");
var syncSubscribe = module.ImportReference(helperDefinition.Methods.Single(method =>
method.Name == "Subscribe" && method.HasGenericParameters));
var asyncSubscribe = module.ImportReference(helperDefinition.Methods.Single(method =>
method.Name == "SubscribeAsync" && method.HasGenericParameters));
var legacyAsyncSubscribe = module.ImportReference(helperDefinition.Methods.Single(method =>
method.Name == "SubscribeAsyncLegacy" && method.HasGenericParameters));
var interfaceDefinition = generatedInterface.Resolve()
?? throw new InvalidOperationException("IShrinkGeneratedSubscriber could not be resolved.");
var interfaceMethod = module.ImportReference(interfaceDefinition.Methods.Single(method =>
method.Name == "AttachGenerated"));
var generatedMethod = new MethodDefinition(
"ShrinkEventBus.IShrinkGeneratedSubscriber.AttachGenerated",
MethodAttributes.Private | MethodAttributes.Final | MethodAttributes.HideBySig |
MethodAttributes.NewSlot | MethodAttributes.Virtual,
disposableType);
generatedMethod.Parameters.Add(new ParameterDefinition("resolver", ParameterAttributes.None, resolverType));
generatedMethod.Parameters.Add(new ParameterDefinition("defaultBus", ParameterAttributes.Optional,
nullableBusKey));
generatedMethod.Overrides.Add(interfaceMethod);
generatedMethod.Body.InitLocals = true;
var bindingLocal = new VariableDefinition(bindingType);
generatedMethod.Body.Variables.Add(bindingLocal);
var il = generatedMethod.Body.GetILProcessor();
il.Emit(OpCodes.Newobj, bindingCtor);
il.Emit(OpCodes.Stloc, bindingLocal);
var classDefaultBus = ReadStringProperty(
type.CustomAttributes.First(attribute =>
attribute.AttributeType.FullName == "ShrinkEventBus.ShrinkEventSubscriberAttribute"),
"DefaultBus");
foreach (var handler in type.Methods.Where(method =>
!method.IsStatic && HasAttribute(method, subscribeAttributeType)).ToArray())
{
EmitGeneratedSubscription(il, module, type, handler,
handler.CustomAttributes.First(attribute =>
attribute.AttributeType.FullName == subscribeAttributeType.FullName),
classDefaultBus, bindingLocal, bindingAdd, syncSubscribe, asyncSubscribe,
legacyAsyncSubscribe, asyncHandlerType);
}
il.Emit(OpCodes.Ldloc, bindingLocal);
il.Emit(OpCodes.Ret);
type.Interfaces.Add(new InterfaceImplementation(generatedInterface));
type.Methods.Add(generatedMethod);
}
private static void EmitGeneratedSubscription(ILProcessor il, ModuleDefinition module,
TypeDefinition ownerType, MethodDefinition handler, CustomAttribute attribute,
string classDefaultBus, VariableDefinition bindingLocal, MethodReference bindingAdd,
MethodReference syncSubscribe, MethodReference asyncSubscribe,
MethodReference legacyAsyncSubscribe, TypeReference asyncHandlerType)
{
if (handler.Parameters.Count is < 1 or > 2)
throw new InvalidOperationException(
$"[ShrinkSubscribe] method {handler.FullName} must have one event parameter and an optional CancellationToken.");
var eventType = module.ImportReference(handler.Parameters[0].ParameterType);
var eventInterface = FindType(module, "ShrinkEventBus.IShrinkEvent", RuntimeAssemblyName)
?? throw new InvalidOperationException("IShrinkEvent was not found.");
if (!ImplementsInterface(eventType, eventInterface.FullName))
throw new InvalidOperationException(
$"[ShrinkSubscribe] method {handler.FullName} event parameter must implement IShrinkEvent.");
var bus = ReadStringProperty(attribute, "Bus");
if (string.IsNullOrWhiteSpace(bus))
bus = classDefaultBus;
var priority = ReadIntProperty(attribute, "Priority", 2);
var numericPriority = ReadIntProperty(attribute, "NumericPriority", 0);
var receiveCanceled = ReadBoolProperty(attribute, "ReceiveCanceled", false);
MethodReference openSubscribe;
TypeReference delegateType;
if (handler.ReturnType.FullName == module.TypeSystem.Void.FullName && handler.Parameters.Count == 1)
{
openSubscribe = syncSubscribe;
delegateType = MakeGenericType(module, typeof(Action<>), eventType);
}
else if (handler.ReturnType.FullName == "Cysharp.Threading.Tasks.UniTask" &&
handler.Parameters.Count == 1)
{
openSubscribe = legacyAsyncSubscribe;
var uniTaskType = FindType(module, "Cysharp.Threading.Tasks.UniTask", "UniTask")
?? module.ImportReference(handler.ReturnType);
delegateType = MakeGenericType(module, typeof(Func<,>), eventType, uniTaskType);
}
else if (handler.ReturnType.FullName == "Cysharp.Threading.Tasks.UniTask" &&
handler.Parameters.Count == 2 &&
handler.Parameters[1].ParameterType.FullName == typeof(System.Threading.CancellationToken).FullName)
{
openSubscribe = asyncSubscribe;
var closedAsyncHandler = new GenericInstanceType(asyncHandlerType);
closedAsyncHandler.GenericArguments.Add(eventType);
delegateType = closedAsyncHandler;
}
else
{
throw new InvalidOperationException(
$"Unsupported [ShrinkSubscribe] signature: {handler.FullName}. Use void(T), UniTask(T), or UniTask(T, CancellationToken).");
}
var closedSubscribe = new GenericInstanceMethod(openSubscribe);
closedSubscribe.GenericArguments.Add(eventType);
var delegateCtor = MakeDelegateConstructor(module, delegateType);
il.Emit(OpCodes.Ldloc, bindingLocal);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_2);
il.Emit(OpCodes.Ldstr, bus ?? string.Empty);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldftn, module.ImportReference(handler));
il.Emit(OpCodes.Newobj, delegateCtor);
il.Emit(OpCodes.Ldc_I4, priority);
il.Emit(OpCodes.Ldc_I4, numericPriority);
il.Emit(receiveCanceled ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Call, closedSubscribe);
il.Emit(OpCodes.Callvirt, bindingAdd);
}
private static void InjectStaticBootstrap(ModuleDefinition module,
IReadOnlyList<TypeDefinition> subscriberTypes, TypeReference subscribeAttributeType)
{
var registryType = FindType(module, "ShrinkEventBus.ShrinkStaticBindingRegistry", RuntimeAssemblyName)
?? throw new InvalidOperationException("ShrinkStaticBindingRegistry was not found.");
var asyncHandlerType = FindType(module, "ShrinkEventBus.ShrinkAsyncEventHandler`1", RuntimeAssemblyName)
?? throw new InvalidOperationException("ShrinkAsyncEventHandler was not found.");
var registryDefinition = registryType.Resolve()
?? throw new InvalidOperationException("ShrinkStaticBindingRegistry could not be resolved.");
var syncRegister = module.ImportReference(registryDefinition.Methods.Single(method =>
method.Name == "Register" && method.HasGenericParameters));
var asyncRegister = module.ImportReference(registryDefinition.Methods.Single(method =>
method.Name == "RegisterAsync" && method.HasGenericParameters));
var legacyAsyncRegister = module.ImportReference(registryDefinition.Methods.Single(method =>
method.Name == "RegisterAsyncLegacy" && method.HasGenericParameters));
var bootstrap = new TypeDefinition("ShrinkEventBus.Generated",
"ShrinkGeneratedStaticBindings",
TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.NotPublic,
module.TypeSystem.Object);
module.Types.Add(bootstrap);
var register = new MethodDefinition("Register",
MethodAttributes.Assembly | MethodAttributes.Static | MethodAttributes.HideBySig,
module.TypeSystem.Void);
bootstrap.Methods.Add(register);
var il = register.Body.GetILProcessor();
foreach (var type in subscriberTypes)
{
var classDefaultBus = ReadStringProperty(
type.CustomAttributes.First(attribute =>
attribute.AttributeType.FullName == "ShrinkEventBus.ShrinkEventSubscriberAttribute"),
"DefaultBus");
foreach (var handler in type.Methods.Where(method =>
method.IsStatic && HasAttribute(method, subscribeAttributeType)).ToArray())
{
EmitStaticGeneratedSubscription(il, module, handler,
handler.CustomAttributes.First(attribute =>
attribute.AttributeType.FullName == subscribeAttributeType.FullName),
classDefaultBus, syncRegister, asyncRegister,
legacyAsyncRegister, asyncHandlerType);
}
}
il.Emit(OpCodes.Ret);
InjectModuleInitializer(module, register);
}
private static void EmitStaticGeneratedSubscription(ILProcessor il, ModuleDefinition module,
MethodDefinition handler, CustomAttribute attribute, string classDefaultBus,
MethodReference syncRegister, MethodReference asyncRegister,
MethodReference legacyAsyncRegister, TypeReference asyncHandlerType)
{
if (handler.Parameters.Count is < 1 or > 2)
throw new InvalidOperationException(
$"[ShrinkSubscribe] method {handler.FullName} must have one event parameter and an optional CancellationToken.");
var eventType = module.ImportReference(handler.Parameters[0].ParameterType);
var eventInterface = FindType(module, "ShrinkEventBus.IShrinkEvent", RuntimeAssemblyName)
?? throw new InvalidOperationException("IShrinkEvent was not found.");
if (!ImplementsInterface(eventType, eventInterface.FullName))
throw new InvalidOperationException(
$"[ShrinkSubscribe] method {handler.FullName} event parameter must implement IShrinkEvent.");
var bus = ReadStringProperty(attribute, "Bus");
if (string.IsNullOrWhiteSpace(bus))
bus = classDefaultBus;
var priority = ReadIntProperty(attribute, "Priority", 2);
var numericPriority = ReadIntProperty(attribute, "NumericPriority", 0);
var receiveCanceled = ReadBoolProperty(attribute, "ReceiveCanceled", false);
MethodReference openRegister;
TypeReference delegateType;
if (handler.ReturnType.FullName == module.TypeSystem.Void.FullName && handler.Parameters.Count == 1)
{
openRegister = syncRegister;
delegateType = MakeGenericType(module, typeof(Action<>), eventType);
}
else if (handler.ReturnType.FullName == "Cysharp.Threading.Tasks.UniTask" &&
handler.Parameters.Count == 1)
{
openRegister = legacyAsyncRegister;
var uniTaskType = FindType(module, "Cysharp.Threading.Tasks.UniTask", "UniTask")
?? module.ImportReference(handler.ReturnType);
delegateType = MakeGenericType(module, typeof(Func<,>), eventType, uniTaskType);
}
else if (handler.ReturnType.FullName == "Cysharp.Threading.Tasks.UniTask" &&
handler.Parameters.Count == 2 &&
handler.Parameters[1].ParameterType.FullName == typeof(System.Threading.CancellationToken).FullName)
{
openRegister = asyncRegister;
var closedAsyncHandler = new GenericInstanceType(asyncHandlerType);
closedAsyncHandler.GenericArguments.Add(eventType);
delegateType = closedAsyncHandler;
}
else
{
throw new InvalidOperationException(
$"Unsupported static [ShrinkSubscribe] signature: {handler.FullName}.");
}
var closedRegister = new GenericInstanceMethod(openRegister);
closedRegister.GenericArguments.Add(eventType);
var delegateCtor = MakeDelegateConstructor(module, delegateType);
var handlerBridge = CreateStaticHandlerBridge(module, handler);
il.Emit(OpCodes.Ldstr, bus ?? string.Empty);
il.Emit(OpCodes.Ldnull);
il.Emit(OpCodes.Ldftn, module.ImportReference(handlerBridge));
il.Emit(OpCodes.Newobj, delegateCtor);
il.Emit(OpCodes.Ldc_I4, priority);
il.Emit(OpCodes.Ldc_I4, numericPriority);
il.Emit(receiveCanceled ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Call, closedRegister);
}
private static MethodDefinition CreateStaticHandlerBridge(ModuleDefinition module,
MethodDefinition handler)
{
var bridge = new MethodDefinition(
$"ShrinkEventBus.GeneratedStaticHandler_{handler.MetadataToken.ToInt32():X8}",
MethodAttributes.Assembly | MethodAttributes.Static | MethodAttributes.HideBySig,
module.ImportReference(handler.ReturnType));
for (var i = 0; i < handler.Parameters.Count; i++)
{
var parameter = handler.Parameters[i];
bridge.Parameters.Add(new ParameterDefinition(parameter.Name, parameter.Attributes,
module.ImportReference(parameter.ParameterType)));
}
var il = bridge.Body.GetILProcessor();
for (var i = 0; i < bridge.Parameters.Count; i++)
il.Emit(OpCodes.Ldarg, bridge.Parameters[i]);
il.Emit(OpCodes.Call, module.ImportReference(handler));
il.Emit(OpCodes.Ret);
handler.DeclaringType.Methods.Add(bridge);
return bridge;
}
private static void InjectModuleInitializer(ModuleDefinition module, MethodReference register)
{
var moduleType = module.Types.First(type => type.Name == "<Module>");
var initializer = moduleType.Methods.FirstOrDefault(method => method.Name == ".cctor");
if (initializer == null)
{
initializer = new MethodDefinition(".cctor",
MethodAttributes.Private | MethodAttributes.Static |
MethodAttributes.HideBySig | MethodAttributes.SpecialName |
MethodAttributes.RTSpecialName,
module.TypeSystem.Void);
initializer.Body.GetILProcessor().Emit(OpCodes.Ret);
moduleType.Methods.Add(initializer);
}
var processor = initializer.Body.GetILProcessor();
processor.InsertBefore(initializer.Body.Instructions[0],
processor.Create(OpCodes.Call, register));
}
private static GenericInstanceType MakeGenericType(ModuleDefinition module, Type openType,
params TypeReference[] arguments)
{
var result = new GenericInstanceType(module.ImportReference(openType));
foreach (var argument in arguments)
result.GenericArguments.Add(argument);
return result;
}
private static MethodReference MakeDelegateConstructor(ModuleDefinition module, TypeReference delegateType)
{
var ctor = new MethodReference(".ctor", module.TypeSystem.Void, delegateType)
{
HasThis = true,
CallingConvention = MethodCallingConvention.Default
};
ctor.Parameters.Add(new ParameterDefinition(module.TypeSystem.Object));
ctor.Parameters.Add(new ParameterDefinition(module.TypeSystem.IntPtr));
return ctor;
}
private static bool ImplementsInterface(TypeReference type, string interfaceFullName)
{
TypeDefinition? current;
try
{
current = type.Resolve();
}
catch
{
return false;
}
while (current != null)
{
if (current.Interfaces.Any(item => item.InterfaceType.FullName == interfaceFullName))
return true;
try
{
current = current.BaseType?.Resolve();
}
catch
{
return false;
}
}
return false;
}
private static string ReadStringProperty(CustomAttribute attribute, string name)
{
foreach (var property in attribute.Properties)
{
if (property.Name == name)
return property.Argument.Value as string ?? string.Empty;
}
return string.Empty;
}
private static int ReadIntProperty(CustomAttribute attribute, string name, int defaultValue)
{
foreach (var property in attribute.Properties)
{
if (property.Name == name)
return Convert.ToInt32(property.Argument.Value);
}
return defaultValue;
}
private static bool ReadBoolProperty(CustomAttribute attribute, string name, bool defaultValue)
{
foreach (var property in attribute.Properties)
{
if (property.Name == name)
return Convert.ToBoolean(property.Argument.Value);
}
return defaultValue;
}
private static TypeReference? FindType(ModuleDefinition module, string fullName, string assemblyName)
{
var resolved = Type.GetType($"{fullName}, {assemblyName}", false);
return resolved == null ? null : module.ImportReference(resolved);
}
private static AssemblyDefinition AssemblyDefinitionFor(ICompiledAssembly compiledAssembly)
{
var assemblyResolver = new PostProcessorAssemblyResolver(compiledAssembly);
var readerParameters = new ReaderParameters
{
SymbolStream = new MemoryStream(compiledAssembly.InMemoryAssembly.PdbData.ToArray()),
SymbolReaderProvider = new PdbReaderProvider(),
AssemblyResolver = assemblyResolver,
ReflectionImporterProvider = new PostProcessorReflectionImporterProvider(),
ReadingMode = ReadingMode.Immediate
};
var assemblyDefinition = AssemblyDefinition.ReadAssembly(
new MemoryStream(compiledAssembly.InMemoryAssembly.PeData.ToArray()),
readerParameters);
assemblyResolver.AddAssemblyDefinitionBeingOperatedOn(assemblyDefinition);
return assemblyDefinition;
}
private static ILPostProcessResult GetResult(AssemblyDefinition assemblyDefinition, List<DiagnosticMessage> diagnostics)
{
var pe = new MemoryStream();
var pdb = new MemoryStream();
assemblyDefinition.Write(pe, new WriterParameters
{
SymbolWriterProvider = new PdbWriterProvider(),
SymbolStream = pdb,
WriteSymbols = true
});
return new ILPostProcessResult(new InMemoryAssembly(pe.ToArray(), pdb.ToArray()), diagnostics);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5f611b284dae01a46bc990b87b8bca90
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,107 @@
#nullable enable
using System.Collections.Generic;
using System.IO;
using System.Threading;
using Mono.Cecil;
using Unity.CompilationPipeline.Common.ILPostProcessing;
namespace ShrinkEventBus.CodeGen
{
public sealed class PostProcessorAssemblyResolver : IAssemblyResolver
{
private readonly string[] _references;
private readonly Dictionary<string, AssemblyDefinition> _cache = new();
private AssemblyDefinition? _self;
public PostProcessorAssemblyResolver(ICompiledAssembly compiledAssembly)
{
_references = compiledAssembly.References;
}
public void AddAssemblyDefinitionBeingOperatedOn(AssemblyDefinition assemblyDefinition)
{
_self = assemblyDefinition;
}
public AssemblyDefinition? Resolve(AssemblyNameReference name)
{
return Resolve(name, new ReaderParameters(ReadingMode.Deferred));
}
public AssemblyDefinition? Resolve(AssemblyNameReference name, ReaderParameters parameters)
{
lock (_cache)
{
if (name.Name == _self?.Name.Name)
return _self;
var path = FindPath(name);
if (path == null)
return null;
var key = $"{path}{File.GetLastWriteTime(path)}";
if (_cache.TryGetValue(key, out var cached))
return cached;
parameters.AssemblyResolver = this;
var ms = ReadFileWithRetry(path);
var pdbPath = Path.ChangeExtension(path, ".pdb");
if (File.Exists(pdbPath))
parameters.SymbolStream = ReadFileWithRetry(pdbPath);
var assembly = AssemblyDefinition.ReadAssembly(ms, parameters);
_cache[key] = assembly;
return assembly;
}
}
private string? FindPath(AssemblyNameReference name)
{
foreach (var reference in _references)
{
if (Path.GetFileNameWithoutExtension(reference) == name.Name)
return reference;
}
var dirs = new HashSet<string>();
foreach (var reference in _references)
{
var dir = Path.GetDirectoryName(reference);
if (dir != null)
dirs.Add(dir);
}
foreach (var dir in dirs)
{
var candidate = Path.Combine(dir, $"{name.Name}.dll");
if (File.Exists(candidate))
return candidate;
}
return null;
}
private static MemoryStream ReadFileWithRetry(string path, int retries = 5)
{
for (var i = 0; i < retries; i++)
{
try
{
return new MemoryStream(File.ReadAllBytes(path));
}
catch (IOException) when (i < retries - 1)
{
Thread.Sleep(100);
}
}
throw new IOException($"[ShrinkEventBus.CodeGen] 无法读取文件: {path}");
}
public void Dispose()
{
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: aeea50f82bab4ee2833c671d801c95e3
timeCreated: 1772908894
@@ -0,0 +1,37 @@
#nullable enable
using System.Linq;
using System.Reflection;
using Mono.Cecil;
namespace ShrinkEventBus.CodeGen
{
public sealed class PostProcessorReflectionImporter : DefaultReflectionImporter
{
private const string CoreLibName = "System.Private.CoreLib";
private readonly AssemblyNameReference? _corlib;
public PostProcessorReflectionImporter(ModuleDefinition module)
: base(module)
{
_corlib = module.AssemblyReferences.FirstOrDefault(
assembly => assembly.Name is "mscorlib" or "netstandard");
}
public override AssemblyNameReference ImportReference(AssemblyName reference)
{
if (_corlib != null && reference.Name == CoreLibName)
return _corlib;
return base.ImportReference(reference);
}
}
public sealed class PostProcessorReflectionImporterProvider : IReflectionImporterProvider
{
public IReflectionImporter GetReflectionImporter(ModuleDefinition module)
{
return new PostProcessorReflectionImporter(module);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0a6c2401798b42f0bbcde72796d2fa9c
timeCreated: 1772908906
@@ -0,0 +1,23 @@
{
"name": "Unity.ShrinkEventBus.CodeGen",
"rootNamespace": "ShrinkEventBus.CodeGen",
"references": [
"ShrinkEventBus.Runtime"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": true,
"overrideReferences": true,
"precompiledReferences": [
"Mono.Cecil.dll",
"Mono.Cecil.Mdb.dll",
"Mono.Cecil.Pdb.dll",
"Mono.Cecil.Rocks.dll"
],
"autoReferenced": false,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 91161d4c2ae3ae74c9184ba33d9aa52e
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: