From ca981bf88fa46a4166915adc1cb369ad7fbe9f28 Mon Sep 17 00:00:00 2001 From: hadashi Date: Fri, 23 Apr 2021 13:43:34 +0900 Subject: [PATCH 1/2] Fix an error in CodeGen that failed to get System.Type (Unity 2021) --- .../Editor/CodeGen/InjectionILGenerator.cs | 21 ++++++++++++++++--- .../CodeGen/VContainerILPostProcessor.cs | 5 ++++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/VContainer/Assets/VContainer/Editor/CodeGen/InjectionILGenerator.cs b/VContainer/Assets/VContainer/Editor/CodeGen/InjectionILGenerator.cs index e1503d30..cb7d68f4 100644 --- a/VContainer/Assets/VContainer/Editor/CodeGen/InjectionILGenerator.cs +++ b/VContainer/Assets/VContainer/Editor/CodeGen/InjectionILGenerator.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Reflection; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Cecil.Rocks; @@ -15,6 +16,7 @@ namespace VContainer.Editor.CodeGen sealed class InjectionILGenerator { readonly ModuleDefinition module; + readonly Assembly assembly; readonly IList targetNamespaces; TypeReference ObjectResolverTypeRef => @@ -54,9 +56,13 @@ sealed class InjectionILGenerator MethodReference resolveMethodRef; MethodReference resolveOrParameterMethodRef; - public InjectionILGenerator(ModuleDefinition module, IList targetNamespaces) + public InjectionILGenerator( + ModuleDefinition module, + Assembly assembly, + IList targetNamespaces) { this.module = module; + this.assembly = assembly; this.targetNamespaces = targetNamespaces; } @@ -110,9 +116,18 @@ public bool TryGenerate(out List diagnosticMessages) bool TryGenerate(TypeDefinition typeDef, List diagnosticMessages) { - var type = Type.GetType($"{typeDef.FullName}, {module.Assembly.FullName}"); + var type = assembly.GetType(typeDef.FullName); + if (type == null) + { + diagnosticMessages.Add(new DiagnosticMessage + { + DiagnosticType = DiagnosticType.Warning, + MessageData = $"Skip IL waving because cant detect type: {typeDef.FullName}" + }); + return false; + } - if (type == null || !NeedsInjectType(type)) + if (!NeedsInjectType(type)) return false; InjectTypeInfo injectTypeInfo; diff --git a/VContainer/Assets/VContainer/Editor/CodeGen/VContainerILPostProcessor.cs b/VContainer/Assets/VContainer/Editor/CodeGen/VContainerILPostProcessor.cs index c9c4ed39..ef3a93ce 100644 --- a/VContainer/Assets/VContainer/Editor/CodeGen/VContainerILPostProcessor.cs +++ b/VContainer/Assets/VContainer/Editor/CodeGen/VContainerILPostProcessor.cs @@ -1,5 +1,6 @@ using System.IO; using System.Linq; +using System.Reflection; using Unity.CompilationPipeline.Common.Diagnostics; using Unity.CompilationPipeline.Common.ILPostProcessing; using Mono.Cecil; @@ -25,8 +26,10 @@ public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly) if (!WillProcess(compiledAssembly)) return null; + var assembly = Assembly.Load(compiledAssembly.InMemoryAssembly.PeData); + var assemblyDefinition = Utils.LoadAssemblyDefinition(compiledAssembly); - var generator = new InjectionILGenerator(assemblyDefinition.MainModule, null); + var generator = new InjectionILGenerator(assemblyDefinition.MainModule, assembly, null); if (generator.TryGenerate(out var diagnosticMessages)) { From 206cdfa794083d0cd10ecb64abec710f498ac3ec Mon Sep 17 00:00:00 2001 From: hadashi Date: Fri, 23 Apr 2021 14:03:19 +0900 Subject: [PATCH 2/2] Make sure that Assembly.Load is only necessary --- .../Editor/CodeGen/InjectionILGenerator.cs | 60 ++++++++++++------- .../CodeGen/VContainerILPostProcessor.cs | 4 +- 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/VContainer/Assets/VContainer/Editor/CodeGen/InjectionILGenerator.cs b/VContainer/Assets/VContainer/Editor/CodeGen/InjectionILGenerator.cs index cb7d68f4..3c282fea 100644 --- a/VContainer/Assets/VContainer/Editor/CodeGen/InjectionILGenerator.cs +++ b/VContainer/Assets/VContainer/Editor/CodeGen/InjectionILGenerator.cs @@ -1,12 +1,14 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Linq; using System.Reflection; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Cecil.Rocks; using Unity.CompilationPipeline.Common.Diagnostics; +using Unity.CompilationPipeline.Common.ILPostProcessing; using MethodAttributes = Mono.Cecil.MethodAttributes; using TypeAttributes = Mono.Cecil.TypeAttributes; using VContainer.Internal; @@ -16,9 +18,11 @@ namespace VContainer.Editor.CodeGen sealed class InjectionILGenerator { readonly ModuleDefinition module; - readonly Assembly assembly; + readonly ICompiledAssembly compiledAssembly; readonly IList targetNamespaces; + Assembly currentAssembly; + TypeReference ObjectResolverTypeRef => objectResolverTypeRef ?? (objectResolverTypeRef = module.ImportReference(typeof(IObjectResolver))); @@ -58,11 +62,11 @@ sealed class InjectionILGenerator public InjectionILGenerator( ModuleDefinition module, - Assembly assembly, - IList targetNamespaces) + ICompiledAssembly compiledAssembly, + IList targetNamespaces = null) { this.module = module; - this.assembly = assembly; + this.compiledAssembly = compiledAssembly; this.targetNamespaces = targetNamespaces; } @@ -76,9 +80,11 @@ public bool TryGenerate(out List diagnosticMessages) foreach (var typeDef in module.Types) { + if (typeDef.FullName == "") continue; + try { - if (TryGenerate(typeDef, diagnosticMessages)) + if (TryGenerateType(typeDef, diagnosticMessages)) { count += 1; } @@ -114,9 +120,35 @@ public bool TryGenerate(out List diagnosticMessages) return false; } - bool TryGenerate(TypeDefinition typeDef, List diagnosticMessages) + bool NeedsInjectType(Type type) + => !type.IsEnum && + !type.IsValueType && + !type.IsInterface && + !(type.IsAbstract && type.IsSealed) && + !typeof(Delegate).IsAssignableFrom(type) && + !typeof(Attribute).IsAssignableFrom(type) && + !type.IsGenericType && + (targetNamespaces == null || + targetNamespaces.Count <= 0 || + targetNamespaces.Contains(type.Namespace)); + + Type GetTypeFromDef(TypeDefinition typeDef) + { + try + { + return Type.GetType($"{typeDef.FullName}, {module.Assembly.FullName}"); + } + catch (FileLoadException) + { + if (currentAssembly == null) + currentAssembly = Assembly.Load(compiledAssembly.InMemoryAssembly.PeData); + return currentAssembly.GetType(typeDef.FullName); + } + } + + bool TryGenerateType(TypeDefinition typeDef, List diagnosticMessages) { - var type = assembly.GetType(typeDef.FullName); + var type = GetTypeFromDef(typeDef); if (type == null) { diagnosticMessages.Add(new DiagnosticMessage @@ -140,7 +172,7 @@ bool TryGenerate(TypeDefinition typeDef, List diagnosticMessa diagnosticMessages.Add(new DiagnosticMessage { DiagnosticType = DiagnosticType.Warning, - MessageData = $"Failed to analyze {type.FullName} : {ex.Message}" + MessageData = $"Failed to analyze {type.FullName} : {ex.GetType()} {ex.Message}" }); return false; } @@ -149,18 +181,6 @@ bool TryGenerate(TypeDefinition typeDef, List diagnosticMessa return true; } - bool NeedsInjectType(Type type) - => !type.IsEnum && - !type.IsValueType && - !type.IsInterface && - !(type.IsAbstract && type.IsSealed) && - !typeof(Delegate).IsAssignableFrom(type) && - !typeof(Attribute).IsAssignableFrom(type) && - !type.IsGenericType && - (targetNamespaces == null || - targetNamespaces.Count <= 0 || - targetNamespaces.Contains(type.Namespace)); - void GenerateInnerInjectorType(TypeDefinition typeDef, InjectTypeInfo injectTypeInfo) { var injectorTypeDef = new TypeDefinition( diff --git a/VContainer/Assets/VContainer/Editor/CodeGen/VContainerILPostProcessor.cs b/VContainer/Assets/VContainer/Editor/CodeGen/VContainerILPostProcessor.cs index ef3a93ce..2477d59b 100644 --- a/VContainer/Assets/VContainer/Editor/CodeGen/VContainerILPostProcessor.cs +++ b/VContainer/Assets/VContainer/Editor/CodeGen/VContainerILPostProcessor.cs @@ -26,10 +26,8 @@ public override ILPostProcessResult Process(ICompiledAssembly compiledAssembly) if (!WillProcess(compiledAssembly)) return null; - var assembly = Assembly.Load(compiledAssembly.InMemoryAssembly.PeData); - var assemblyDefinition = Utils.LoadAssemblyDefinition(compiledAssembly); - var generator = new InjectionILGenerator(assemblyDefinition.MainModule, assembly, null); + var generator = new InjectionILGenerator(assemblyDefinition.MainModule, compiledAssembly, null); if (generator.TryGenerate(out var diagnosticMessages)) {