/// <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"); } var constructor = (Func <object>)DelegateCache.GetOrAdd(type, x => DoCreateDelegate(type)); return(constructor); }
/// <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 identity = new { constructorInfo, validateArguments }; var constructor = (Func <object[], object>)DelegateCache.GetOrAdd( identity, x => DoCreateDelegate(constructorInfo, validateArguments)); return(constructor); }
/// <summary> /// Creates a dynamic method for getting the value of the given property. /// </summary> /// <typeparam name="TSource">The type of the intance from which to get the value.</typeparam> /// <typeparam name="TRet">The type of the return value.</typeparam> /// <param name="propertyInfo"> /// The instance of <see cref="PropertyInfo"/> from which the dynamic method would be created. /// </param> /// <param name="nonPublic"> /// Indicates whether to use the non-public property getter method. /// </param> /// <returns> /// A dynamic method for getting the value of the given property. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="propertyInfo"/> is null.</exception> /// <exception cref="ArgumentException"> /// The property is an indexer. /// -or - /// The get accessor method from <paramref name="propertyInfo"/> cannot be retrieved. /// -or- /// <typeparamref name="TSource"/> is not <see cref="object"/>, and from which /// the declaring type the property is not assignable. /// -or- /// <typeparamref name="TRet"/> is not assignable from the property type. /// </exception> public static Func <TSource, TRet> CreateGetter <TSource, TRet>(PropertyInfo propertyInfo, bool nonPublic) { if (propertyInfo == null) { throw new ArgumentNullException("propertyInfo"); } var identity = new { propertyInfo, nonPublic, sourceType = typeof(TSource), returnType = typeof(TRet) }; var getter = (Func <TSource, TRet>)DelegateCache.GetOrAdd( identity, x => DoCreateGetter <TSource, TRet>(propertyInfo, nonPublic)); return(getter); }
/// <summary> /// Creates a dynamic method for setting the value of the given property. /// </summary> /// <typeparam name="TTarget">The type of the instance the property belongs to.</typeparam> /// <typeparam name="TValue">The type of the value to set.</typeparam> /// <param name="propertyInfo"> /// The instance of <see cref="PropertyInfo"/> from which the dynamic method would be created. /// </param> /// <param name="nonPublic"> /// Indicates whether to use the non-public property setter method. /// </param> /// <returns> /// A dynamic method for setting the value of the given property. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="propertyInfo"/> is null.</exception> /// <exception cref="ArgumentException"> /// The property is an indexer. /// -or- /// The set accessor method from the <paramref name="propertyInfo"/> cannot be retrieved. /// -or- /// <typeparamref name="TTarget"/> is a value type. /// -or- /// <typeparamref name="TTarget"/> is not <see cref="object"/>, and from which /// the declaring type of <paramref name="propertyInfo"/> is not assignable. /// -or- /// <typeparamref name="TValue"/> is not <see cref="object"/>, and the type of property /// is not assignable from <typeparamref name="TValue"/>. /// </exception> /// <remarks> /// In order to set a property value on a value type succesfully, the value type must be boxed /// in and <see cref="object"/>, and unboxed from the object after the dynamic /// set mothod is called, e.g. /// <code> /// object boxedStruct = new SomeStruct(); /// setter(s, "the value"); /// SomeStruct unboxedStruct = (SomeStruct)boxedStruct; /// </code> /// </remarks> public static Action <TTarget, TValue> CreateSetter <TTarget, TValue>(PropertyInfo propertyInfo, bool nonPublic) { if (propertyInfo == null) { throw new ArgumentNullException("propertyInfo"); } var identity = new { propertyInfo, nonPublic, targetType = typeof(TTarget), valueType = typeof(TValue) }; var setter = (Action <TTarget, TValue>)DelegateCache.GetOrAdd( identity, x => DoCreateSetter <TTarget, TValue>(propertyInfo, nonPublic)); return(setter); }
/// <summary> /// Creates a dynamic method for getting the value of the given field. /// </summary> /// <typeparam name="TSource">The type of the intance from which to get the value.</typeparam> /// <typeparam name="TRet">The type of the return value.</typeparam> /// <param name="fieldInfo"> /// The instance of <see cref="FieldInfo"/> from which the dynamic method would be created. /// </param> /// <returns> /// A dynamic method for getting the value of the given field. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="fieldInfo"/> is null.</exception> /// <exception cref="ArgumentException"> /// <typeparamref name="TSource"/> is not <see cref="object"/>, and from which /// the declaring type of the field is not assignable. /// -or- /// <typeparamref name="TRet"/> is not assignable from the type of the field. /// </exception> public static Func <TSource, TRet> CreateGetter <TSource, TRet>(FieldInfo fieldInfo) { if (fieldInfo == null) { throw new ArgumentNullException("fieldInfo"); } var identity = new { fieldInfo, sourceType = typeof(TSource), returnType = typeof(TRet) }; var getter = (Func <TSource, TRet>)DelegateCache.GetOrAdd( identity, x => DoCreateGetter <TSource, TRet>(fieldInfo)); return(getter); }
/// <summary> /// Creates a dynamic method for setting the value of the given field. /// </summary> /// <typeparam name="TTarget">The type of the instance the field belongs to.</typeparam> /// <typeparam name="TValue">The type of the field value to set.</typeparam> /// <param name="fieldInfo"> /// The instance of <see cref="FieldInfo"/> from which the dynamic method would be created. /// </param> /// <returns> /// A dynamic method for setting the value of the given field. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="fieldInfo"/> is null.</exception> /// <exception cref="ArgumentException"> /// <typeparamref name="TTarget"/> is a value type. /// -or- /// <typeparamref name="TTarget"/> is not <see cref="object"/>, and from which /// the declaring type of <paramref name="fieldInfo"/> is not assignable. /// -or- /// <typeparamref name="TValue"/> is not <see cref="object"/>, and the type of field /// is not assignable from <typeparamref name="TValue"/>. /// </exception> /// <remarks> /// In order to set a field on a value type succesfully, the value type must be boxed /// in and <see cref="object"/>, and unboxed from the object after the dynamic /// set mothod is called, e.g. /// <code> /// object boxedStruct = new SomeStruct(); /// setter(s, "the value"); /// SomeStruct unboxedStruct = (SomeStruct)boxedStruct; /// </code> /// </remarks> public static Action <TTarget, TValue> CreateSetter <TTarget, TValue>(FieldInfo fieldInfo) { if (fieldInfo == null) { throw new ArgumentNullException("fieldInfo"); } var identity = new { fieldInfo, targetType = typeof(TTarget), valueType = typeof(TValue) }; var setter = (Action <TTarget, TValue>)DelegateCache.GetOrAdd( identity, x => DoCreateSetter <TTarget, TValue>(fieldInfo)); return(setter); }
/// <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 identity = new { methodInfo, validateArguments }; var method = (Func <object, object[], object>)DelegateCache.GetOrAdd( identity, x => DoCreateDelegate(methodInfo, validateArguments)); return(method); }