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); }
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); }
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); } }
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); }
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); }
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); }