// void WrapMethodInTryCatch(MethodDefinition method) // { // var il = method.Body.GetILProcessor(); // var top = method.Body.Instructions.First(); // var ret = method.Body.Instructions.Last(); // var leaveTry = Create(OpCodes.Leave, ret); // var leaveCatch = Create(OpCodes.Leave, ret); // var ldthis = Create(OpCodes.Ldarg_0); // var logException = MethodCallInstruction(typeof(UnityEngine.Debug).GetMethod(nameof(UnityEngine.Debug.LogException), new[] { typeof(System.Exception), typeof(UnityEngine.Object) })); // il.InsertBefore(ret, leaveTry); // il.InsertBefore(ret, ldthis); // il.InsertBefore(ret, logException); // il.InsertBefore(ret, leaveCatch); // var handler = new ExceptionHandler(ExceptionHandlerType.Catch) // { // TryStart = top, // TryEnd = ldthis, // HandlerStart = ldthis, // HandlerEnd = ret, // CatchType = module.ImportReference(typeof(System.Exception)), // }; // il.Body.ExceptionHandlers.Add(handler); // } void InsertInjectionCall(MethodDefinition method, FieldDefinition field, CustomAttribute attribute) { var il = method.Body.GetILProcessor(); var top = method.Body.Instructions[0]; bool IsOptional = attribute.PropertyEquals(key: nameof(Inject.Optional), value: true); TypeReference UnwrapArrayType(TypeReference type) => type.IsArray ? type.GetElementType() : type; var elementType = field.FieldType; var(resolveMethodName, useGenericMethodCall, canBeSerialized) = GetNameOfResolveMethodInfo(ref elementType, attribute); elementType = UnwrapArrayType(elementType); var hasSerializeFieldAttribute = field.HasAttribute <UnityEngine.SerializeField>(); if (!canBeSerialized && hasSerializeFieldAttribute) { throw new System.NotSupportedException($"Field of type {field.FieldType.Name} marked with [{attribute.AttributeType.Name}] should not be serialized."); } if (hasSerializeFieldAttribute) #if ODIN_INSPECTOR { field.AddAttribute <Sirenix.OdinInspector.ReadOnlyAttribute>(module); } #else { field.AddAttribute <ReadOnlyAttribute>(module); } #endif Instruction first, last; { il.InsertBefore(top, first = Create(OpCodes.Ldarg_0)); // store field { il.InsertBefore(top, Create(OpCodes.Ldarg_0)); if (useGenericMethodCall) { il.InsertBefore(top, Create(OpCodes.Ldarg_0)); il.InsertBefore(top, Create(OpCodes.Call, module.ImportReference(typeof(Internal.InjectHelpers).GetMethod(resolveMethodName, flags)).MakeGenericInstance(elementType))); } else { // load dependency resolution result { il.InsertBefore(top, Create(OpCodes.Ldarg_0)); // load type { il.InsertBefore(top, Create(OpCodes.Ldtoken, module.ImportReference(elementType))); il.InsertBefore(top, MethodCallInstruction(typeof(System.Type).GetMethod(nameof(System.Type.GetTypeFromHandle), flags))); } il.InsertBefore(top, MethodCallInstruction(typeof(Internal.InjectHelpers).GetMethod(resolveMethodName, flags))); } if (!field.FieldType.IsValueType) { bool isInterface; // enable interface serialization try { isInterface = field.FieldType.Resolve().IsInterface; } catch { isInterface = false; } if (isInterface) { il.InsertBefore(top, Create(OpCodes.Isinst, module.ImportReference(typeof(UnityEngine.Object)))); } else { il.InsertBefore(top, Create(OpCodes.Isinst, field.FieldType)); } } } il.InsertBefore(top, Create(OpCodes.Stfld, field)); } // no-op (jump label) il.InsertBefore(top, last = Create(OpCodes.Nop)); if (!IsOptional && !field.FieldType.IsValueType) { il.InsertBefore(last, Create(OpCodes.Ldfld, field)); il.InsertBefore(last, Create(OpCodes.Brtrue_S, last)); il.InsertBefore(last, Create(OpCodes.Ldstr, FormatLog($"Failed to initialize @*|{field.FieldType.Name} {field.Name}|*@ in component @*|{method.DeclaringType.FullName}|*@.\n|Component injection using *[{attribute.AttributeType.FullName.Replace('/', '.')}]*|")) ); il.InsertBefore(last, Create(OpCodes.Ldarg_0)); if (hasSerializeFieldAttribute) { il.InsertBefore(last, MethodCallInstruction(typeof(UnityEngine.Debug).GetMethod(nameof(UnityEngine.Debug.LogError), new[] { typeof(string), typeof(UnityEngine.Object) }))); } else { il.InsertBefore(last, MethodCallInstruction(typeof(UnityEngine.Debug).GetMethod(nameof(UnityEngine.Debug.LogWarning), new[] { typeof(string), typeof(UnityEngine.Object) }))); } } } // isdirty editor injection guard if (hasSerializeFieldAttribute) { il.InsertBefore(first, Create(OpCodes.Ldarg_0)); il.InsertBefore(first, MethodCallInstruction(typeof(Internal.InjectHelpers).GetMethod(nameof(ShouldUpdateInjectedComponents), flags))); il.InsertBefore(first, Create(OpCodes.Brfalse, last)); } WrapBlockInTryCatch(il, first, last); }