コード例 #1
0
        public void Build()
        {
            var type = method.DeclaringType;

            genericType = type;
            if (type.HasGenericParameters)
            {
                genericType = type.MakeGenericInstanceType(type.GenericParameters.ToArray());
            }

            var proceedClassName = weaver.GenerateUniqueName(method, extensionPoint.AttributeType, "Proceed");

            proceedStruct = new TypeDefinition(method.DeclaringType.Namespace, proceedClassName, TypeAttributes.NestedPrivate | WeaverContext.Struct, weaver.Context.ValueType);

            proceedStructConstructor = null;
            if (!method.IsStatic)
            {
                instanceField = new FieldDefinition("$this", FieldAttributes.Private, genericType);
                proceedStruct.Fields.Add(instanceField);

                proceedStructConstructor = new MethodDefinition(".ctor", WeaverContext.Constructor, weaver.TypeSystem.VoidReference);
                proceedStructConstructor.Parameters.Add(new ParameterDefinition(genericType));
                proceedStructConstructor.Body            = new MethodBody(proceedStructConstructor);
                proceedStructConstructor.Body.InitLocals = true;
                proceedStructConstructor.Body.Emit(il =>
                {
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Ldarg_1);
                    il.Emit(OpCodes.Stfld, instanceField);
                    il.Emit(OpCodes.Ret);
                });
                proceedStruct.Methods.Add(proceedStructConstructor);
                proceedStructConstructorReference = proceedStructConstructor;
            }
            else
            {
                proceedStructConstructorReference = null;
            }

            method.DeclaringType.CopyGenericParameters(proceedStruct);
            method.CopyGenericParameters(proceedStruct);
            method.DeclaringType.NestedTypes.Add(proceedStruct);

            var original = method.MoveImplementation($"{method.Name}$Original");

            proceedStruct.Methods.Add(Proceed);

            ProceedReference = Proceed;
            TypeReference genericProceedType = proceedStruct;

            if (type.HasGenericParameters || method.HasGenericParameters)
            {
                genericProceedType = proceedStruct.MakeGenericInstanceType(type.GenericParameters.Concat(method.GenericParameters).ToArray());
                ProceedReference   = Proceed.Bind((GenericInstanceType)genericProceedType);
                proceedStructConstructorReference = proceedStructConstructor?.Bind((GenericInstanceType)genericProceedType);
            }
            proceedStructType = genericProceedType;

            genericProceedTargetMethod = original;

            if (type.HasGenericParameters || method.HasGenericParameters)
            {
                var genericMethodArguments = proceedStruct.GenericParameters.Skip(type.GenericParameters.Count).ToArray();
                genericProceedTargetMethod = genericProceedTargetMethod.BindMethod(genericType, genericMethodArguments);
            }
        }