private static Action <TTarget, TValue> EmitFieldSetter <TTarget, TValue>(FieldInfo fieldInfo) { var dynamicMethod = EmitUtils.CreateDynamicMethod( "$Set" + fieldInfo.Name, null, new[] { typeof(TTarget), typeof(TValue) }, fieldInfo.DeclaringType); var il = dynamicMethod.GetILGenerator(); //copy the value to a local variable, unbox if needed il.DeclareLocal(fieldInfo.FieldType); il.Ldarg_1(); if (!typeof(TValue).IsValueType) { il.CastValue(fieldInfo.FieldType); } il.Stloc_0(); if (fieldInfo.IsStatic) { il.Ldloc_0(); il.Stsfld(fieldInfo); } else { il.Ldarg_0(); il.CastReference(fieldInfo.DeclaringType); il.Ldloc_0(); il.Stfld(fieldInfo); } il.Ret(); return((Action <TTarget, TValue>)dynamicMethod.CreateDelegate(typeof(Action <TTarget, TValue>))); }
private static Action <TTarget, TValue> EmitPropertySetter <TTarget, TValue>( PropertyInfo propertyInfo, MethodInfo setMethod) { var propType = propertyInfo.PropertyType; var declaringType = propertyInfo.DeclaringType; var dynamicMethod = EmitUtils.CreateDynamicMethod( "$Set" + propertyInfo.Name, null, new[] { typeof(TTarget), typeof(TValue) }, declaringType); var il = dynamicMethod.GetILGenerator(); //copy the value to a local variable, unbox if needed il.DeclareLocal(propType); il.Ldarg_1(); if (!typeof(TValue).IsValueType) { il.CastValue(propType); } il.Stloc_0(); //push the instance, unbox if needed if (!setMethod.IsStatic) { il.Ldarg_0(); il.CastReference(declaringType); } //push the value and call the method il.Ldloc_0(); il.CallMethod(setMethod); il.Ret(); return((Action <TTarget, TValue>)dynamicMethod.CreateDelegate(typeof(Action <TTarget, TValue>))); }
/// <summary> /// Creates a dynamic method for creating instances of the given type. /// The given type must have a public parameterless constructor. /// </summary> /// <param name="type">The type of the instances to be created.</param> /// <returns> /// A dynamic method for creating instances of the given type. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="type"/> is null.</exception> /// <exception cref="ArgumentException"> /// The given type is an interface, or is abstract, /// or does not have a public parameterless constructor. /// </exception> public static Func <object> CreateDelegate(Type type) { if (type == null) { throw new ArgumentNullException("type"); } if (type.IsInterface) { throw new ArgumentException(string.Format("{0} is an interface.", type), "type"); } if (type.IsAbstract) { throw new ArgumentException(string.Format("{0} is abstract.", type), "type"); } ConstructorInfo constructorInfo = null; if (type.IsClass) { constructorInfo = type.GetConstructor(Type.EmptyTypes); if (constructorInfo == null) { throw new ArgumentException( string.Format("{0} does not have a public parameterless constructor.", type), "type"); } } var dynamicMethod = EmitUtils.CreateDynamicMethod( "$Create" + type, typeof(object), Type.EmptyTypes, type); var il = dynamicMethod.GetILGenerator(); if (type.IsClass) { il.Newobj(constructorInfo); } else //value type { il.DeclareLocal(type); il.LoadLocalVariableAddress(0); il.Initobj(type); il.LoadLocalVariable(0); il.Box(type); } il.Ret(); return((Func <object>)dynamicMethod.CreateDelegate(typeof(Func <object>))); }
private static Func <TSource, TReturn> EmitFieldGetter <TSource, TReturn>(FieldInfo fieldInfo) { var dynamicMethod = EmitUtils.CreateDynamicMethod( "$Get" + fieldInfo.Name, typeof(TReturn), new[] { typeof(TSource) }, fieldInfo.DeclaringType); var il = dynamicMethod.GetILGenerator(); if (fieldInfo.IsStatic) { il.Ldsfld(fieldInfo); } else { //unbox the source if needed if (typeof(TSource).IsValueType) { il.Ldarga_S(0); } else { il.Ldarg_0(); il.CastReference(fieldInfo.DeclaringType); } il.Ldfld(fieldInfo); } //box the return value if needed if (!typeof(TReturn).IsValueType && fieldInfo.FieldType.IsValueType) { il.Box(fieldInfo.FieldType); } il.Ret(); return((Func <TSource, TReturn>)dynamicMethod.CreateDelegate(typeof(Func <TSource, TReturn>))); }
private static Func <TSource, TReturn> EmitPropertyGetter <TSource, TReturn>( PropertyInfo propertyInfo, MethodInfo getMethod) { var dynamicMethod = EmitUtils.CreateDynamicMethod( "$Get" + propertyInfo.Name, typeof(TReturn), new[] { typeof(TSource) }, propertyInfo.DeclaringType); var il = dynamicMethod.GetILGenerator(); if (!getMethod.IsStatic) { //unbox the input value if needed if (typeof(TSource).IsValueType) { il.Ldarga_S(0); } else { il.Ldarg_0(); il.CastReference(propertyInfo.DeclaringType); } } il.CallMethod(getMethod); //box the return value if needed if (!typeof(TReturn).IsValueType && propertyInfo.PropertyType.IsValueType) { il.Box(propertyInfo.PropertyType); } il.Ret(); return((Func <TSource, TReturn>)dynamicMethod.CreateDelegate(typeof(Func <TSource, TReturn>))); }
/// <summary> /// Creates a dynamic method for invoking the method from the given <see cref="MethodInfo"/> /// and indicates whether to perform a arguments validation in the dynamic method. /// </summary> /// <param name="methodInfo"> /// The instance of <see cref="MemberInfo"/> from which the dyanmic method is to be created. /// </param> /// <param name="validateArguments"> /// If <c>true</c>, the dynamic method will validate if the instance or the array of arguments /// is null and check the length of the array to avoid the exceptions such as /// <see cref="NullReferenceException"/> or <see cref="IndexOutOfRangeException"/>, /// an <see cref="ArgumentNullException"/> or <see cref="ArgumentException"/> will be thrown instead. /// </param> /// <returns> /// The delegate has two parameters: the first for the object instance (will be ignored /// if the method is static), and the second for the arguments of the method (will be /// ignored if the method has no arguments)/ /// The return value of the delegate will be <c>null</c> if the method has no return value. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="methodInfo"/> is null.</exception> public static Func <object, object[], object> CreateDelegate( MethodInfo methodInfo, bool validateArguments) { if (methodInfo == null) { throw new ArgumentNullException("methodInfo"); } var args = methodInfo.GetParameters(); var dynamicMethod = EmitUtils.CreateDynamicMethod( "$Call" + methodInfo.Name, typeof(object), new[] { typeof(object), typeof(object[]) }, methodInfo.DeclaringType); var il = dynamicMethod.GetILGenerator(); var lableValidationCompleted = il.DefineLabel(); if (!validateArguments || (methodInfo.IsStatic && args.Length == 0)) { il.Br_S(lableValidationCompleted); //does not need validation } else { var lableCheckArgumentsRef = il.DefineLabel(); var lableCheckArgumentsLength = il.DefineLabel(); //check if the instance is null if (!methodInfo.IsStatic) { // if (instance == null) throw new ArgumentNullExcpeiton("instance"); il.Ldarg_0(); il.Brtrue_S(args.Length > 0 ? lableCheckArgumentsRef : lableValidationCompleted); il.ThrowArgumentsNullExcpetion("instance"); } //check the arguments if (args.Length > 0) { // if (arguments == null) throw new ArgumentNullExcpeiton("arguments"); il.MarkLabel(lableCheckArgumentsRef); il.Ldarg_1(); il.Brtrue_S(lableCheckArgumentsLength); il.ThrowArgumentsNullExcpetion("arguments"); // if (arguments.Length < $(args.Length)) throw new ArgumentExcpeiton(msg, "arguments"); il.MarkLabel(lableCheckArgumentsLength); il.Ldarg_1(); il.Ldlen(); il.Conv_I4(); il.LoadInt32(args.Length); il.Bge_S(lableValidationCompleted); il.ThrowArgumentsExcpetion("Not enough arguments in the argument array.", "arguments"); } } il.MarkLabel(lableValidationCompleted); if (!methodInfo.IsStatic) { il.Ldarg_0(); il.CastReference(methodInfo.DeclaringType); } if (args.Length > 0) { for (int i = 0; i < args.Length; i++) { il.Ldarg_1(); il.LoadInt32((short)i); il.Ldelem_Ref(); il.CastValue(args[i].ParameterType); } } il.CallMethod(methodInfo); if (methodInfo.ReturnType == typeof(void)) { il.Ldc_I4_0(); //return null } else { il.BoxIfNeeded(methodInfo.ReturnType); } il.Ret(); var methodDelegate = dynamicMethod.CreateDelegate(typeof(Func <object, object[], object>)); return((Func <object, object[], object>)methodDelegate); }
/// <summary> /// Creates a dynamic method for creating instances from the given <see cref="ConstructorInfo"/> /// and indicates whether to perform a arguments validation in the dynamic method. /// </summary> /// <param name="constructorInfo">The constructor from which instances will be created.</param> /// <param name="validateArguments"> /// If <c>true</c>, the dynamic method will validate if the array of arguments is null /// and check the length of the array to avoid the exceptions such as /// <see cref="NullReferenceException"/> or <see cref="IndexOutOfRangeException"/>, /// an <see cref="ArgumentNullException"/> or <see cref="ArgumentException"/> will be thrown instead. /// </param> /// <returns> /// A dynamic method for creating instances from the given constructor, the method receives an /// array as the arguments of the constructor. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="constructorInfo"/> is null. /// </exception> /// <exception cref="ArgumentException"> /// The declaring type of the construcor is abstract. /// </exception> public static Func <object[], object> CreateDelegate(ConstructorInfo constructorInfo, bool validateArguments) { if (constructorInfo == null) { throw new ArgumentNullException("constructorInfo"); } var delclaringType = constructorInfo.DeclaringType; if (delclaringType.IsAbstract) { throw new ArgumentException( "The declaring type of the constructor is abstract.", "constructorInfo"); } var dynamicMethod = EmitUtils.CreateDynamicMethod( "$Create" + delclaringType.Name, typeof(object), new[] { typeof(object[]) }, constructorInfo.DeclaringType); var il = dynamicMethod.GetILGenerator(); var args = constructorInfo.GetParameters(); var lableValidationCompleted = il.DefineLabel(); if (!validateArguments || args.Length == 0) { il.Br_S(lableValidationCompleted); } else { var lableCheckArgumentsLength = il.DefineLabel(); // if (arguments == null) throw new ArgumentNullExcpeiton("arguments"); il.Ldarg_0(); il.Brtrue_S(lableCheckArgumentsLength); il.ThrowArgumentsNullExcpetion("arguments"); // if (arguments.Length < $(args.Length)) throw new ArgumentExcpeiton(msg, "arguments"); il.MarkLabel(lableCheckArgumentsLength); il.Ldarg_0(); il.Ldlen(); il.Conv_I4(); il.LoadInt32(args.Length); il.Bge_S(lableValidationCompleted); il.ThrowArgumentsExcpetion("Not enough arguments in the argument array.", "arguments"); } il.MarkLabel(lableValidationCompleted); if (args.Length > 0) { for (int i = 0; i < args.Length; i++) { il.Ldarg_0(); il.LoadInt32((short)i); il.Ldelem_Ref(); il.CastValue(args[i].ParameterType); } } il.Newobj(constructorInfo); il.Ret(); return((Func <object[], object>)dynamicMethod.CreateDelegate(typeof(Func <object[], object>))); }