コード例 #1
0
        private MethodBuilder DefineMethodAndParameters(ProxyScope proxyScope, MethodDefinition methodDefinition)
        {
            MethodBuilder methodBuilder = proxyScope.DefineMethod(methodDefinition.Name, methodDefinition.MethodAttributes);

            methodBuilder.SetReturnType(methodDefinition.ReturnType);

            // parameters
            methodBuilder.DefineGenericParameters(methodDefinition.GenericArguments);
            if (methodDefinition.ParameterDefinitions.Length > 0)
            {
                DefineParameters(methodBuilder, methodDefinition);
            }
            return(methodBuilder);
        }
コード例 #2
0
        public void DefineMethod_Adds_MethodBuilder()
        {
            var moduleScope    = new ModuleScope();
            var generator      = new ProxyGenerator(moduleScope);
            var typeDefinition = generator.GetTypeDefinition(typeof(EmpyType), null, null);

            TypeBuilder typeBulder = moduleScope.Module.DefineType(typeDefinition.FullName, typeDefinition.TypeAttributes);

            var proxyScope = new ProxyScope(moduleScope, typeBulder, typeDefinition);

            proxyScope.DefineTypeAndMembers();

            Assert.AreEqual(0, proxyScope.Methods.Count);

            var m = proxyScope.DefineMethod("M", MethodAttributes.Public, typeof(string), new Type[] { typeof(string) });

            Assert.AreEqual(1, proxyScope.Methods.Count);
            Assert.AreEqual("M", proxyScope.Methods[0].Name);

            var m2 = proxyScope.DefineMethod("M2", MethodAttributes.Public);

            Assert.AreEqual(2, proxyScope.Methods.Count);
            Assert.AreEqual("M2", proxyScope.Methods[1].Name);
        }
コード例 #3
0
        public void CreateOnPropertyChangedMethod(ProxyScope proxyScope)
        {
            FieldBuilder eventField = proxyScope.Fields.FirstOrDefault(p => p.Name == EventName);

            if (eventField == null)
            {
                throw new ArgumentException($"No field '{EventName}' found.");
            }

            var onPropertyChangedMethodBuilder = GetOnPropertyChangedMethod(proxyScope);

            if (onPropertyChangedMethodBuilder == null)
            {
                onPropertyChangedMethodBuilder = proxyScope.DefineMethod(MethodName, MethodAttributes.Family, typeof(void), new Type[] { typeof(string) });

                onPropertyChangedMethodBuilder.DefineParameter(1, ParameterAttributes.None, ParameterName);

                var il = onPropertyChangedMethodBuilder.GetILGenerator();

                var isNullLocal = il.DeclareLocal(typeof(bool));
                var label       = il.DefineLabel();

                il.Emit(OpCodes.Nop);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, eventField);
                il.Emit(OpCodes.Ldnull);
                il.Emit(OpCodes.Cgt_Un);
                il.Emit(OpCodes.Stloc, isNullLocal);
                il.Emit(OpCodes.Ldloc, isNullLocal);
                il.Emit(OpCodes.Brfalse_S, label);

                il.Emit(OpCodes.Nop);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, eventField);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Newobj, PropertyChangedEventArgsConstructor);
                il.Emit(OpCodes.Callvirt, InvokeMethod);

                il.MarkLabel(label);

                il.Emit(OpCodes.Nop);
                il.Emit(OpCodes.Ret);
            }
        }
コード例 #4
0
        protected virtual MethodBuilder CreateDelegateCommand(ProxyScope proxyScope, string commandName, MethodInfo executeMethod, MethodInfo canExecuteMethod)
        {
            if (commandName is null)
            {
                throw new ArgumentNullException(nameof(commandName));
            }
            if (executeMethod is null)
            {
                throw new ArgumentNullException(nameof(executeMethod));
            }

            Type            parameterType       = GetParameterType(executeMethod);
            Type            delegateCommandType = null;
            ConstructorInfo actionCtor          = null;

            if (parameterType == null)
            {
                delegateCommandType = typeof(DelegateCommand);
                actionCtor          = ActionConstructor;
            }
            else
            {
                delegateCommandType = typeof(DelegateCommand <>).MakeGenericType(new Type[] { parameterType });
                actionCtor          = typeof(Action <>).MakeGenericType(new Type[] { parameterType }).GetConstructors()[0];
            }

            PropertyBuilder propertyBuilder = proxyScope.DefineProperty(commandName, PropertyAttributes.None, delegateCommandType, new Type[0]);

            FieldBuilder field = proxyScope.DefineField($"_{NamingHelper.ToCamelCase(commandName)}", delegateCommandType, FieldAttributes.Private);

            // get method
            MethodBuilder methodBuilder = proxyScope.DefineMethod($"get_{commandName}", MethodAttributes.Public | MethodAttributes.HideBySig, delegateCommandType, new Type[0]);

            // body
            var il = methodBuilder.GetILGenerator();

            var isNullLocal  = il.DeclareLocal(typeof(bool));
            var commandLocal = il.DeclareLocal(delegateCommandType);
            var isNullLabel  = il.DefineLabel();

            il.Emit(OpCodes.Nop);
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldfld, field);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Ceq);
            il.Emit(OpCodes.Stloc, isNullLocal);

            il.Emit(OpCodes.Ldloc, isNullLocal);

            il.Emit(OpCodes.Brfalse_S, isNullLabel);

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldftn, executeMethod);
            il.Emit(OpCodes.Newobj, actionCtor);

            if (canExecuteMethod != null)
            {
                ConstructorInfo delegateCommandWithPredicateCtor = parameterType == null ? DelegateCommandWithPredicateConstructor : delegateCommandType.GetConstructors()[1];
                ConstructorInfo funcCtor = parameterType == null ? FuncBoolConstructor : typeof(Func <,>).MakeGenericType(new Type[] { parameterType, typeof(bool) }).GetConstructors()[0];
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldftn, canExecuteMethod);
                il.Emit(OpCodes.Newobj, funcCtor);
                il.Emit(OpCodes.Newobj, delegateCommandWithPredicateCtor);
            }
            else
            {
                ConstructorInfo delegateCommandCtor = parameterType == null ? DelegateCommandConstructor : delegateCommandType.GetConstructors()[0];
                il.Emit(OpCodes.Newobj, delegateCommandCtor);
            }
            il.Emit(OpCodes.Stfld, field);

            il.MarkLabel(isNullLabel);

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldfld, field);
            il.Emit(OpCodes.Stloc, commandLocal);
            il.Emit(OpCodes.Ldloc, commandLocal);
            il.Emit(OpCodes.Ret);

            // set property method
            propertyBuilder.SetGetMethod(methodBuilder);

            return(methodBuilder);
        }
コード例 #5
0
        public MethodBuilder CreateMethod(ProxyScope proxyScope, CallbackMethodDefinition callbackMethodDefinition)
        {
            AdditionalCode additionalCode = (callbackMethodDefinition.TypeDefinition as ProxyTypeDefinition)?.Options?.AdditionalCode;

            // method
            MethodBuilder methodBuilder = proxyScope.DefineMethod(callbackMethodDefinition.Name, callbackMethodDefinition.MethodAttributes);

            methodBuilder.SetReturnType(callbackMethodDefinition.ReturnType);

            // parameters
            GenericTypeParameterBuilder[] genericTypeParameters = methodBuilder.DefineGenericParameters(callbackMethodDefinition.GenericArguments);
            if (callbackMethodDefinition.ParameterDefinitions.Length > 0)
            {
                DefineParameters(methodBuilder, callbackMethodDefinition);
            }

            // body
            var il = methodBuilder.GetILGenerator();

            // locals
            LocalBuilder resultLocalBuilder = null;
            LocalBuilder targetLocalBuilder = null;
            Type         returnType         = callbackMethodDefinition.ReturnType;

            if (returnType != typeof(void))
            {
                if (returnType.ContainsGenericParameters)
                {
                    resultLocalBuilder = il.DeclareLocal(genericTypeParameters.First(p => p.Name == returnType.Name));
                }
                else
                {
                    resultLocalBuilder = il.DeclareLocal(returnType);
                }
            }
            Type targetType = callbackMethodDefinition.TypeDefinition.TargetType;

            if (targetType != null)
            {
                targetLocalBuilder = il.DeclareLocal(targetType);
            }

            il.Emit(OpCodes.Nop);

            // before
            if (additionalCode != null)
            {
                additionalCode.BeforeInvoke(proxyScope, il, callbackMethodDefinition);
            }

            if (targetType != null)
            {
                // return ((TargetType)target).Method(p1, p2 ...);
                string fieldName = callbackMethodDefinition.TypeDefinition.TargetFieldName;
                EmitHelper.StoreFieldToLocal(il, proxyScope.Fields.First(p => p.Name == fieldName), targetLocalBuilder);
                il.Emit(OpCodes.Ldloc, targetLocalBuilder);
            }
            else
            {
                // return base.Method(p1, p2...);
                il.Emit(OpCodes.Ldarg_0);
            }

            var parameterDefinitions = callbackMethodDefinition.ParameterDefinitions;

            for (int i = 0; i < parameterDefinitions.Length; i++)
            {
                il.EmitLdarg(i + 1);
            }

            if (callbackMethodDefinition.TypeDefinition.TypeDefinitionType == TypeDefinitionType.InterfaceProxy && targetType == null)
            {
                ThrowInterfaceProxyWithoutTargetException(il, callbackMethodDefinition);
            }
            else
            {
                CallMethodOnTarget(il, callbackMethodDefinition, genericTypeParameters);

                if (returnType != typeof(void))
                {
                    il.Emit(OpCodes.Stloc, resultLocalBuilder);
                }

                // after
                if (additionalCode != null)
                {
                    additionalCode.AfterInvoke(proxyScope, il, callbackMethodDefinition);
                }

                if (returnType != typeof(void))
                {
                    il.Emit(OpCodes.Ldloc, resultLocalBuilder);
                }

                il.Emit(OpCodes.Nop);
                il.Emit(OpCodes.Ret);
            }

            return(methodBuilder);
        }
コード例 #6
0
        public virtual MethodBuilder CreateMethod(ProxyScope proxyScope, MethodDefinition methodDefinition, MemberInfo member, FieldBuilder memberField, FieldBuilder callerMethodField)
        {
            MethodInfo method = methodDefinition.Method;

            // callback method
            MethodBuilder callbackMethodBuilder = CreateCallbackMethod(proxyScope, methodDefinition.CallbackMethodDefinition);

            // invocation type
            Type invocationType = GetOrCreateInvocationType(proxyScope, methodDefinition, callbackMethodBuilder);

            // method
            MethodBuilder methodBuilder = proxyScope.DefineMethod(methodDefinition.Name, methodDefinition.MethodAttributes);

            methodBuilder.SetReturnType(methodDefinition.ReturnType);

            // parameters
            methodBuilder.DefineGenericParameters(methodDefinition.GenericArguments);
            if (methodDefinition.ParameterDefinitions.Length > 0)
            {
                DefineParameters(methodBuilder, methodDefinition);
            }

            // attributes
            DefineAttributes(methodBuilder, methodDefinition);

            // method body
            var il = methodBuilder.GetILGenerator();

            // locals
            IInterceptorSelector interceptorSelector      = proxyScope.TypeDefinition.Options?.InterceptorSelector;
            FieldBuilder         interceptorSelectorField = null;
            FieldBuilder         interceptorMethodField   = null;

            if (interceptorSelector != null)
            {
                interceptorSelectorField = FindConstructorField(proxyScope, ProxyScope.InterceptorSelectorFieldName);
                interceptorMethodField   = proxyScope.DefineField(methodDefinition.InterceptorSelectorFieldName, typeof(IInterceptor[]), FieldAttributes.Private);
            }
            var          returnType               = methodDefinition.ReturnType;
            Type         targetType               = methodDefinition.TypeDefinition.TargetType;
            Type         localBuilderType         = targetType != null ? targetType : typeof(object);
            LocalBuilder targetLocalBuilder       = il.DeclareLocal(localBuilderType);       // target
            LocalBuilder interceptorsLocalBuilder = il.DeclareLocal(typeof(IInterceptor[])); // interceptors
            LocalBuilder memberLocalBuilder       = il.DeclareLocal(typeof(MemberInfo));     // MemberInfo
            LocalBuilder callerMethodLocalBuilder = il.DeclareLocal(typeof(MethodInfo));     // proxy method
            LocalBuilder proxyLocalBuilder        = il.DeclareLocal(typeof(object));         // proxy
            LocalBuilder parametersLocalBuilder   = il.DeclareLocal(typeof(object[]));       // parameters
            LocalBuilder invocationLocalBuilder   = il.DeclareLocal(invocationType);         // invocation
            LocalBuilder returnValueLocalBuilder  = null;

            if (returnType != typeof(void))
            {
                returnValueLocalBuilder = il.DeclareLocal(returnType);
            }

            FieldBuilder interceptorsField = proxyScope.ConstructorFields[0];

            if (targetType != null)
            {
                FieldBuilder targetField = FindConstructorField(proxyScope, methodDefinition.TypeDefinition.TargetFieldName);
                EmitHelper.StoreFieldToLocal(il, targetField, targetLocalBuilder);
            }

            EmitHelper.StoreFieldToLocal(il, memberField, memberLocalBuilder);
            EmitHelper.StoreFieldToLocal(il, callerMethodField, callerMethodLocalBuilder);
            EmitHelper.StoreThisToLocal(il, proxyLocalBuilder);

            if (interceptorSelector != null)
            {
                LocalBuilder isNullLocal = il.DeclareLocal(typeof(bool));
                Label        isNullLabel = il.DefineLabel();

                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, interceptorMethodField);
                il.Emit(OpCodes.Ldnull);
                il.Emit(OpCodes.Ceq);
                il.Emit(OpCodes.Stloc, isNullLocal);
                il.Emit(OpCodes.Ldloc, isNullLocal);

                il.Emit(OpCodes.Brfalse_S, isNullLabel);

                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, interceptorSelectorField);
                il.Emit(OpCodes.Ldtoken, member.DeclaringType);
                il.Emit(OpCodes.Call, Methods.GetTypeFromHandle);
                il.Emit(OpCodes.Ldloc, callerMethodLocalBuilder);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, interceptorsField);
                il.Emit(OpCodes.Callvirt, Methods.SelectInterceptorsMethod);
                il.Emit(OpCodes.Stfld, interceptorMethodField);

                il.MarkLabel(isNullLabel);

                EmitHelper.StoreFieldToLocal(il, interceptorMethodField, interceptorsLocalBuilder);
            }
            else
            {
                EmitHelper.StoreFieldToLocal(il, interceptorsField, interceptorsLocalBuilder);
            }

            StoreArgsToArray(il, methodDefinition.ParameterDefinitions, parametersLocalBuilder);

            EmitHelper.CreateInvocation(il, invocationType, targetLocalBuilder, interceptorsLocalBuilder, memberLocalBuilder, callerMethodLocalBuilder, proxyLocalBuilder, parametersLocalBuilder, invocationLocalBuilder);
            EmitHelper.CallProceed(il, invocationLocalBuilder);

            // set ref parameters values after Proceed called
            SetByRefArgs(il, methodDefinition.ParameterDefinitions, invocationLocalBuilder);

            EmitReturnValue(il, method, invocationLocalBuilder, returnValueLocalBuilder);

            if (method.DeclaringType.IsInterface)
            {
                proxyScope.DefineMethodOverride(methodBuilder, method);
            }

            return(methodBuilder);
        }