Example #1
0
    IEnumerable <Instruction> GetAttributeInstanceInstructions(
        ILProcessor processor,
        ICustomAttribute attribute,
        MethodDefinition method,
        VariableDefinition attributeVariableDefinition,
        VariableDefinition methodVariableDefinition,
        bool explicitMatch)
    {
        var getMethodFromHandleRef = referenceFinder.GetMethodReference(methodBaseTypeRef, md => md.Name == "GetMethodFromHandle" &&
                                                                        md.Parameters.Count == 2);

        var getTypeof = referenceFinder.GetMethodReference(systemTypeRef, md => md.Name == "GetTypeFromHandle");
        var ctor      = referenceFinder.GetMethodReference(activatorTypeRef, md => md.Name == "CreateInstance" &&
                                                           md.Parameters.Count == 1);

        var getCustomAttrs = referenceFinder.GetMethodReference(attributeTypeRef,
                                                                md => md.Name == "GetCustomAttributes" &&
                                                                md.Parameters.Count == 2 &&
                                                                md.Parameters[0].ParameterType.FullName == typeof(MemberInfo).FullName &&
                                                                md.Parameters[1].ParameterType.FullName == typeof(Type).FullName);

        /*
         *      // Code size       23 (0x17)
         *        .maxstack  1
         *        .locals init ([0] class SimpleTest.IntersectMethodsMarkedByAttribute i)
         *        IL_0000:  nop
         *        IL_0001:  ldtoken    SimpleTest.IntersectMethodsMarkedByAttribute
         *        IL_0006:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
         *        IL_000b:  call       object [mscorlib]System.Activator::CreateInstance(class [mscorlib]System.Type)
         *        IL_0010:  castclass  SimpleTest.IntersectMethodsMarkedByAttribute
         *        IL_0015:  stloc.0
         *        IL_0016:  ret
         */

        var oInstructions = new List <Instruction>
        {
            processor.Create(OpCodes.Nop),

            processor.Create(OpCodes.Ldtoken, method),
            processor.Create(OpCodes.Ldtoken, method.DeclaringType),
            processor.Create(OpCodes.Call, getMethodFromHandleRef),    // Push method onto the stack, GetMethodFromHandle, result on stack
            processor.Create(OpCodes.Stloc, methodVariableDefinition), // Store method in __fody$method

            processor.Create(OpCodes.Nop),
        };

        if (explicitMatch &&
            method.CustomAttributes.Any(m => m.AttributeType.Equals(attribute.AttributeType)))
        {
            oInstructions.AddRange(new[]
            {
                processor.Create(OpCodes.Ldloc, methodVariableDefinition),
                processor.Create(OpCodes.Ldtoken, attribute.AttributeType),
                processor.Create(OpCodes.Call, getTypeof),
                processor.Create(OpCodes.Call, getCustomAttrs),

                processor.Create(OpCodes.Dup),
                processor.Create(OpCodes.Ldlen),
                processor.Create(OpCodes.Ldc_I4_1),
                processor.Create(OpCodes.Sub),

//                      processor.Create(OpCodes.Ldc_I4_0),
                processor.Create(OpCodes.Ldelem_Ref),

                processor.Create(OpCodes.Castclass, attribute.AttributeType),
                processor.Create(OpCodes.Stloc, attributeVariableDefinition),
            });
        }
        else if (explicitMatch &&
                 method.DeclaringType.CustomAttributes.Any(m => m.AttributeType.Equals(attribute.AttributeType)))
        {
            oInstructions.AddRange(new[]
            {
                processor.Create(OpCodes.Ldtoken, method.DeclaringType),
                processor.Create(OpCodes.Call, getTypeof),
                processor.Create(OpCodes.Ldtoken, attribute.AttributeType),
                processor.Create(OpCodes.Call, getTypeof),
                processor.Create(OpCodes.Call, getCustomAttrs),

                processor.Create(OpCodes.Dup),
                processor.Create(OpCodes.Ldlen),
                processor.Create(OpCodes.Ldc_I4_1),
                processor.Create(OpCodes.Sub),

                processor.Create(OpCodes.Ldelem_Ref),

                processor.Create(OpCodes.Castclass, attribute.AttributeType),
                processor.Create(OpCodes.Stloc, attributeVariableDefinition),
            });
        }
        else
        {
            oInstructions.AddRange(new[]
            {
                processor.Create(OpCodes.Ldtoken, attribute.AttributeType),
                processor.Create(OpCodes.Call, getTypeof),
                processor.Create(OpCodes.Call, ctor),
                processor.Create(OpCodes.Castclass, attribute.AttributeType),
                processor.Create(OpCodes.Stloc, attributeVariableDefinition),
            });
        }

        return(oInstructions);
    }