예제 #1
0
 public Lock(MethodBody body, FieldReference field)
 {
     this.m_Body  = body;
     this.m_Field = field;
     if (field.Resolve().IsStatic)
     {
         body.Emit(OpCodes.Ldsfld, field);
         body.Emit(OpCodes.Call, Lock.m_Enter);
     }
     else
     {
         body.Emit(OpCodes.Ldarg_0);
         body.Emit(OpCodes.Ldsfld, field);
         body.Emit(OpCodes.Call, Lock.m_Enter);
     }
 }
예제 #2
0
        protected virtual void ProxyMethod(MethodBody body, MethodReference proceedTargetMethod)
        {
            // Initialize method info in static constructor
            var methodInfoFieldDefinition = new FieldDefinition(Name + "$Info", FieldAttributes.Private | FieldAttributes.Static, ClassWeaver.Context.MethodInfoType);
            ClassWeaver.ProxyType.Fields.Add(methodInfoFieldDefinition);
            FieldReference methodInfoField = methodInfoFieldDefinition;

            FieldReference propertyInfoField = null;
            PropertyDefinition property = null;
            if (Method.IsSetter || Method.IsGetter)
            {
                property = ClassWeaver.PropertiesByAccessor[Method];
                var propertyInfoFieldDeclaration = new FieldDefinition($"{Name}${(Method.IsGetter ? "Get" : "Set")}Info", FieldAttributes.Private | FieldAttributes.Static, ClassWeaver.Context.PropertyInfoType);
                ClassWeaver.ProxyType.Fields.Add(propertyInfoFieldDeclaration);
                propertyInfoField = propertyInfoFieldDeclaration;
            }

            StaticConstructor.Body.Emit(il =>
            {
                var methodDeclaringType = Import(Method.DeclaringType);
                if (ClassWeaver.ProxyType.HasGenericParameters)
                {
                    var genericProxyType = ClassWeaver.ProxyType.MakeGenericInstanceType(ClassWeaver.ProxyType.GenericParameters.ToArray());
                    methodInfoField = methodInfoField.Bind(genericProxyType);
                    propertyInfoField = propertyInfoField?.Bind(genericProxyType);
                    methodDeclaringType = ClassWeaver.SourceType.MakeGenericInstanceType(ClassWeaver.ProxyType.GenericParameters.ToArray());
                }

                var methodFinder = ClassWeaver.Context.MethodFinder.MakeGenericInstanceType(methodDeclaringType);

                // Store MethodInfo into the static field
                var methodSignature = Method.GenerateSignature();
                var findMethod = ClassWeaver.Context.FindMethod.Bind(methodFinder);
                il.Emit(OpCodes.Ldstr, methodSignature);
                il.Emit(OpCodes.Call, findMethod);
                il.Emit(OpCodes.Stsfld, methodInfoField);

                if (property != null)
                {
                    // Store PropertyInfo into the static field
                    var findProperty = ClassWeaver.Context.FindProperty.Bind(methodFinder);
                    il.Emit(OpCodes.Ldstr, methodSignature);
                    il.Emit(OpCodes.Call, findProperty);
                    il.Emit(OpCodes.Stsfld, propertyInfoField);
                }
            });

            // Create proceed method (four different types).  The proceed method is what you may call in your invocation handler
            // in order to invoke the behavior that would have happened without the proxy.  The actual behavior depends on the value
            // of "target".  If it's not null, it calls the equivalent method on "target".  If it *is* null, then:
            //
            // * If it's an interface, it provides a default value
            // * If it's not an interface, and the method is not abstract, it calls the base implementation of that class.
            // * If it's abstract, then it provides a default value
            //
            // The actual implementation of proceed varies based on whether (where T represents the method's return type):
            //
            // * The method's return type is void               (Represented by Action)
            // * The method's return type is Task               (Represented by Func<Task>)
            // * The method's return type is Task<T>            (Represented by Func<Task<T>>)
            // * The method's return type is anything else      (Represented by Func<T>)
            SetUpTypes();

            var proceed = new MethodDefinition("Proceed", MethodAttributes.Public | MethodAttributes.Static, ProceedReturnType.ResolveGenericParameter(ClassWeaver.ProxyType));
            proceed.Parameters.Add(new ParameterDefinition(ClassWeaver.Context.InvocationType));
            proceed.Body = new MethodBody(proceed);
            proceed.Body.InitLocals = true;
            ProceedClass.Methods.Add(proceed);

            MethodReference proceedReference = proceed;
            TypeReference proceedClass = ProceedClass;

            if (ProceedClass.HasGenericParameters)
            {
                proceedReference = proceed.Bind(proceedClass.MakeGenericInstanceType(ClassWeaver.ProxyType.GenericParameters.Concat(body.Method.GenericParameters).ToArray()));
            }

            proceed.Body.Emit(il =>
            {
                ImplementProceed(Method, body, il, methodInfoField, proceedReference, EmitProceedTarget, proceedTargetMethod, GetProceedCallOpCode());
            });

            // Implement method
            body.Emit(il =>
            {
                ImplementBody(il, methodInfoField, propertyInfoField, proceedReference, proceedTargetMethod);
            });
        }
예제 #3
0
        protected virtual void ProxyMethod(MethodBody body, MethodReference proceedTargetMethod)
        {
            // Initialize method info in static constructor
            var methodInfoFieldDefinition = new FieldDefinition(Name + "$Info", FieldAttributes.Private | FieldAttributes.Static, ClassWeaver.Context.MethodInfoType);

            ClassWeaver.ProxyType.Fields.Add(methodInfoFieldDefinition);
            FieldReference methodInfoField = methodInfoFieldDefinition;

            FieldReference     propertyInfoField = null;
            PropertyDefinition property          = null;

            if (Method.IsSetter || Method.IsGetter)
            {
                property = ClassWeaver.PropertiesByAccessor[Method];
                var propertyInfoFieldDeclaration = new FieldDefinition($"{Name}${(Method.IsGetter ? "Get" : "Set")}Info", FieldAttributes.Private | FieldAttributes.Static, ClassWeaver.Context.PropertyInfoType);
                ClassWeaver.ProxyType.Fields.Add(propertyInfoFieldDeclaration);
                propertyInfoField = propertyInfoFieldDeclaration;
            }

            StaticConstructor.Body.Emit(il =>
            {
                var methodDeclaringType = Import(Method.DeclaringType);
                if (ClassWeaver.ProxyType.HasGenericParameters)
                {
                    var genericProxyType = ClassWeaver.ProxyType.MakeGenericInstanceType(ClassWeaver.ProxyType.GenericParameters.ToArray());
                    methodInfoField      = methodInfoField.Bind(genericProxyType);
                    propertyInfoField    = propertyInfoField?.Bind(genericProxyType);
                    methodDeclaringType  = ClassWeaver.SourceType.MakeGenericInstanceType(ClassWeaver.ProxyType.GenericParameters.ToArray());
                }

                var methodFinder = ClassWeaver.Context.MethodFinder.MakeGenericInstanceType(methodDeclaringType);

                // Store MethodInfo into the static field
                var methodSignature = Method.GenerateSignature();
                var findMethod      = ClassWeaver.Context.FindMethod.Bind(methodFinder);
                il.Emit(OpCodes.Ldstr, methodSignature);
                il.Emit(OpCodes.Call, findMethod);
                il.Emit(OpCodes.Stsfld, methodInfoField);

                if (property != null)
                {
                    // Store PropertyInfo into the static field
                    var findProperty = ClassWeaver.Context.FindProperty.Bind(methodFinder);
                    il.Emit(OpCodes.Ldstr, methodSignature);
                    il.Emit(OpCodes.Call, findProperty);
                    il.Emit(OpCodes.Stsfld, propertyInfoField);
                }
            });

            // Create proceed method (four different types).  The proceed method is what you may call in your invocation handler
            // in order to invoke the behavior that would have happened without the proxy.  The actual behavior depends on the value
            // of "target".  If it's not null, it calls the equivalent method on "target".  If it *is* null, then:
            //
            // * If it's an interface, it provides a default value
            // * If it's not an interface, and the method is not abstract, it calls the base implementation of that class.
            // * If it's abstract, then it provides a default value
            //
            // The actual implementation of proceed varies based on whether (where T represents the method's return type):
            //
            // * The method's return type is void               (Represented by Action)
            // * The method's return type is Task               (Represented by Func<Task>)
            // * The method's return type is Task<T>            (Represented by Func<Task<T>>)
            // * The method's return type is anything else      (Represented by Func<T>)
            SetUpTypes();

            var proceed = new MethodDefinition("Proceed", MethodAttributes.Public | MethodAttributes.Static, ProceedReturnType.ResolveGenericParameter(ClassWeaver.ProxyType));

            proceed.Parameters.Add(new ParameterDefinition(ClassWeaver.Context.InvocationType));
            proceed.Body            = new MethodBody(proceed);
            proceed.Body.InitLocals = true;
            ProceedClass.Methods.Add(proceed);

            MethodReference proceedReference = proceed;
            TypeReference   proceedClass     = ProceedClass;

            if (ProceedClass.HasGenericParameters)
            {
                proceedReference = proceed.Bind(proceedClass.MakeGenericInstanceType(ClassWeaver.ProxyType.GenericParameters.Concat(body.Method.GenericParameters).ToArray()));
            }

            proceed.Body.Emit(il =>
            {
                ImplementProceed(Method, body, il, methodInfoField, proceedReference, EmitProceedTarget, proceedTargetMethod, GetProceedCallOpCode());
            });

            // Implement method
            body.Emit(il =>
            {
                ImplementBody(il, methodInfoField, propertyInfoField, proceedReference, proceedTargetMethod);
            });
        }