/// <summary> /// Creates a delegate which can set the value of the field specified by <paramref name="name"/> and /// matching <paramref name="bindingFlags"/> on the given <paramref name="type"/>. /// </summary> public static MemberSetter DelegateForSetFieldValue(this Type type, string name, Flags bindingFlags) { var callInfo = new CallInfo(type, null, bindingFlags, MemberTypes.Field, name, null, null, false); return((MemberSetter) new MemberSetEmitter(callInfo).GetDelegate()); }
/// <summary> /// Returns true if at least one of the values in the given <paramref name="mask"/> are set in the current Flags instance. /// </summary> public bool IsAnySet(Flags mask) { return((flags & mask) != 0); }
/// <summary> /// Gets all public and non-public instance fields and properties on the given <paramref name="type"/> /// that match the specified <paramref name="bindingFlags"/>, including members defined on base types. /// </summary> /// <returns>A list of all matching members on the type. This value will never be null.</returns> public static IList <MemberInfo> FieldsAndProperties(this Type type, Flags bindingFlags) { return(type.Members(MemberTypes.Field | MemberTypes.Property, bindingFlags, null)); }
/// <summary> /// Sets the field specified by <paramref name="name"/> and matching <paramref name="bindingFlags"/> /// on the given <paramref name="obj"/> to the specified <paramref name="value" />. /// </summary> /// <returns><paramref name="obj"/>.</returns> public static object SetFieldValue(this object obj, string name, object value, Flags bindingFlags) { DelegateForSetFieldValue(obj.GetTypeAdjusted(), name, bindingFlags)(obj, value); return(obj); }
/// <summary> /// Creates a delegate which can invoke the constructor whose parameter types are <paramref name="parameterTypes" /> /// and matching <paramref name="bindingFlags"/> on the given <paramref name="type"/>. /// Leave <paramref name="parameterTypes"/> empty if the constructor has no argument. /// </summary> public static ConstructorInvoker DelegateForCreateInstance(this Type type, Flags bindingFlags, params Type[] parameterTypes) { return((ConstructorInvoker) new CtorInvocationEmitter(type, bindingFlags, parameterTypes).GetDelegate()); }
/// <summary> /// Gets all members of the given <paramref name="memberTypes"/> on the given <paramref name="type"/> that /// match the specified <paramref name="bindingFlags"/>, optionally filtered by the supplied <paramref name="names"/> /// list (in accordance with the given <paramref name="bindingFlags"/>). /// </summary> /// <param name="type">The type to reflect on.</param> /// <param name="memberTypes">The <see href="MemberTypes"/> to include in the result.</param> /// <param name="bindingFlags">The <see cref="BindingFlags"/> or <see cref="Flags"/> combination used to define /// the search behavior and result filtering.</param> /// <param name="names">The optional list of names against which to filter the result. If this parameter is /// <c>null</c> or empty no name filtering will be applied. The default behavior is to check for an exact, /// case-sensitive match. Pass <see href="Flags.ExcludeExplicitlyImplemented"/> to exclude explicitly implemented /// interface members, <see href="Flags.PartialNameMatch"/> to locate by substring, and /// <see href="Flags.IgnoreCase"/> to ignore case.</param> /// <returns>A list of all matching members on the type. This value will never be null.</returns> public static IList <MemberInfo> Members(this Type type, MemberTypes memberTypes, Flags bindingFlags, params string[] names) { if (type == null || type == typeof(object)) { return(new MemberInfo[0]); } bool recurse = bindingFlags.IsNotSet(Flags.DeclaredOnly); bool hasNames = names != null && names.Length > 0; bool hasSpecialFlags = bindingFlags.IsAnySet(Flags.ExcludeBackingMembers | Flags.ExcludeExplicitlyImplemented | Flags.ExcludeHiddenMembers); if (!recurse && !hasNames && !hasSpecialFlags) { return(type.FindMembers(memberTypes, bindingFlags, null, null)); } var members = GetMembers(type, memberTypes, bindingFlags); members = hasSpecialFlags ? members.Filter(bindingFlags) : members; members = hasNames ? members.Filter(bindingFlags, names) : members; return(members); }
/// <summary> /// Creates a delegate which can invoke the method <paramref name="name"/> with arguments matching /// <paramref name="parameterTypes"/> and matching <paramref name="bindingFlags"/> on the given <paramref name="type"/>. /// Leave <paramref name="parameterTypes"/> empty if the method has no arguments. /// </summary> public static MethodInvoker DelegateForCallMethod(this Type type, string name, Flags bindingFlags, params Type[] parameterTypes) { return(DelegateForCallMethod(type, null, name, bindingFlags, parameterTypes)); }
/// <summary> /// Invokes a constructor whose parameter types are inferred from <paramref name="parameters" /> and /// matching <paramref name="bindingFlags"/> on the given <paramref name="type"/> /// with <paramref name="parameters" /> being the arguments. /// Leave <paramref name="parameters"/> empty if the constructor has no argument. /// </summary> /// <remarks> /// All elements of <paramref name="parameters"/> must not be <c>null</c>. Otherwise, /// <see cref="NullReferenceException"/> is thrown. If you are not sure as to whether /// any element is <c>null</c> or not, use the overload that accepts <c>paramTypes</c> array. /// </remarks> /// <seealso cref="CreateInstance(System.Type,System.Type[],Fasterflect.Flags,object[])"/> public static object CreateInstance(this Type type, Flags bindingFlags, params object[] parameters) { return(DelegateForCreateInstance(type, bindingFlags, parameters.ToTypeArray())(parameters)); }
/// <summary> /// Returns a new Flags instance returns a new Flags instance with the values from <paramref name="flags"/> /// that were not in <paramref name="mask"/> if <paramref name="condition"/> is true, and otherwise returns /// the supplied <paramref name="flags"/>. /// </summary> public static Flags ClearIf(Flags flags, Flags mask, bool condition) { return(condition ? (Flags)(flags & ~mask) : flags); }
/// <summary> /// Invoke generic method. See the overload with same parameters except for <paramref name="genericTypes"/>. /// </summary> /// <seealso cref="CallMethod(object,string,Type[],Flags,object[])"/> public static object CallMethod(this object obj, Type[] genericTypes, string name, Type[] parameterTypes, Flags bindingFlags, params object[] parameters) { return(DelegateForCallMethod(obj.GetTypeAdjusted(), genericTypes, name, bindingFlags, parameterTypes) (obj, parameters)); }
/// <summary> /// Returns a new Flags instance with the union of the values from <paramref name="flags"/> and /// <paramref name="mask"/> if <paramref name="condition"/> is true, and otherwise returns a new /// Flags instance with the values from <paramref name="flags"/> that were not in <paramref name="mask"/>. /// </summary> public static Flags SetOnlyIf(Flags flags, Flags mask, bool condition) { return(condition ? flags | mask : (Flags)(flags & ~mask)); }
/// <summary> /// Returns a new Flags instance with the union of the values from <paramref name="flags"/> and /// <paramref name="mask"/> if <paramref name="condition"/> is true, and otherwise returns the /// supplied <paramref name="flags"/>. /// </summary> public static Flags SetIf(Flags flags, Flags mask, bool condition) { return(condition ? flags | mask : flags); }
/// <summary> /// Returns true if all values in the given <paramref name="mask"/> are not set in the current Flags instance. /// </summary> public bool IsNotSet(Flags mask) { return((flags & mask) == 0); }
/// <summary> /// Invokes the method specified by <paramref name="name"/> on the given <paramref name="obj"/> /// matching <paramref name="bindingFlags"/> using <paramref name="parameters"/> as arguments. /// Leave <paramref name="parameters"/> empty if the method has no argument. /// </summary> /// <returns>The return value of the method.</returns> /// <remarks>If the method has no return type, <c>null</c> is returned.</remarks> /// <remarks> /// All elements of <paramref name="parameters"/> must not be <c>null</c>. Otherwise, /// <see cref="NullReferenceException"/> is thrown. If you are not sure as to whether /// any element is <c>null</c> or not, use the overload that accepts <c>paramTypes</c> array. /// </remarks> /// <seealso cref="CallMethod(object,string,System.Type[],Fasterflect.Flags,object[])"/> public static object CallMethod(this object obj, string name, Flags bindingFlags, params object[] parameters) { return(DelegateForCallMethod(obj.GetTypeAdjusted(), null, name, bindingFlags, parameters.ToTypeArray()) (obj, parameters)); }
/// <summary> /// Create a delegate to invoke a generic method. See the overload with same parameters except for <paramref name="genericTypes"/>. /// </summary> /// <seealso cref="DelegateForCallMethod(Type,string,Flags,Type[])"/> public static MethodInvoker DelegateForCallMethod(this Type type, Type[] genericTypes, string name, Flags bindingFlags, params Type[] parameterTypes) { var callInfo = new CallInfo(type, genericTypes, bindingFlags, MemberTypes.Method, name, parameterTypes, null, true); return((MethodInvoker) new MethodInvocationEmitter(callInfo).GetDelegate()); }
/// <summary> /// Gets all constructors matching the given <paramref name="bindingFlags"/> (and that are not abstract) /// on the given <paramref name="type"/>. /// </summary> /// <param name="type">The type to reflect on.</param> /// <param name="bindingFlags">The search criteria to use when reflecting.</param> /// <returns>A list of matching constructors. This value will never be null.</returns> public static IList <ConstructorInfo> Constructors(this Type type, Flags bindingFlags) { return(type.GetTypeInfo().GetConstructors(bindingFlags)); //.Where( ci => !ci.IsAbstract ).ToList(); }
/// <summary> /// Gets the method with the given <paramref name="name"/> and matching <paramref name="bindingFlags"/> /// on the given <paramref name="type"/>. /// </summary> /// <param name="type">The type on which to reflect.</param> /// <param name="name">The name of the method to search for. This argument must be supplied. The /// default behavior is to check for an exact, case-sensitive match. Pass <see href="Flags.ExplicitNameMatch"/> /// to include explicitly implemented interface members, <see href="Flags.PartialNameMatch"/> to locate /// by substring, and <see href="Flags.IgnoreCase"/> to ignore case.</param> /// <param name="bindingFlags">The <see cref="BindingFlags"/> or <see cref="Flags"/> combination used to define /// the search behavior and result filtering.</param> /// <returns>The specified method or null if no method was found. If there are multiple matches /// due to method overloading the first found match will be returned.</returns> public static MethodInfo Method(this Type type, string name, Flags bindingFlags) { return(type.Method(name, null, bindingFlags)); }
/// <summary> /// Invokes a constructor whose parameter types are <paramref name="parameterTypes" /> and /// matching <paramref name="bindingFlags"/> on the given <paramref name="type"/> /// with <paramref name="parameters" /> being the arguments. /// </summary> public static object CreateInstance(this Type type, Type[] parameterTypes, Flags bindingFlags, params object[] parameters) { return(DelegateForCreateInstance(type, bindingFlags, parameterTypes)(parameters)); }
/// <summary> /// Gets a generic method. See the overload with same arguments exception for <paramref name="genericTypes"/>. /// </summary> /// <seealso cref="Method(Type,string,Flags)"/> public static MethodInfo Method(this Type type, Type[] genericTypes, string name, Flags bindingFlags) { return(type.Method(genericTypes, name, null, bindingFlags)); }
/// <summary> /// Gets all public and non-public instance members on the given <paramref name="type"/> that /// match the specified <paramref name="bindingFlags"/>. /// </summary> /// <returns>A list of all matching members on the type. This value will never be null.</returns> /// <param name="type">The type to reflect on.</param> /// <param name="bindingFlags">The <see cref="BindingFlags"/> or <see cref="Flags"/> combination used to define /// the search behavior and result filtering.</param> /// <returns>A list of all matching members on the type. This value will never be null.</returns> public static IList <MemberInfo> Members(this Type type, Flags bindingFlags) { return(type.Members(MemberTypes.All, bindingFlags, null)); }
/// <summary> /// Gets the method with the given <paramref name="name"/> and matching <paramref name="bindingFlags"/> /// on the given <paramref name="type"/> where the parameter types correspond in order with the /// supplied <paramref name="parameterTypes"/>. /// </summary> /// <param name="type">The type on which to reflect.</param> /// <param name="name">The name of the method to search for. This argument must be supplied. The /// default behavior is to check for an exact, case-sensitive match. Pass <see href="Flags.ExplicitNameMatch"/> /// to include explicitly implemented interface members, <see href="Flags.PartialNameMatch"/> to locate /// by substring, and <see href="Flags.IgnoreCase"/> to ignore case.</param> /// <param name="parameterTypes">If this parameter is supplied then only methods with the same parameter signature /// will be included in the result. The default behavior is to check only for assignment compatibility, /// but this can be changed to exact matching by passing <see href="Flags.ExactBinding"/>.</param> /// <param name="bindingFlags">The <see cref="BindingFlags"/> or <see cref="Flags"/> combination used to define /// the search behavior and result filtering.</param> /// <returns>The specified method or null if no method was found. If there are multiple matches /// due to method overloading the first found match will be returned.</returns> public static MethodInfo Method(this Type type, string name, Type[] parameterTypes, Flags bindingFlags) { return(type.Method(null, name, parameterTypes, bindingFlags)); }
private static IList <MemberInfo> GetMembers(Type type, MemberTypes memberTypes, Flags bindingFlags) { bool recurse = bindingFlags.IsNotSet(Flags.DeclaredOnly); if (!recurse) { return(type.FindMembers(memberTypes, bindingFlags, null, null)); } bindingFlags |= Flags.DeclaredOnly; bindingFlags &= ~BindingFlags.FlattenHierarchy; var members = new List <MemberInfo>(); members.AddRange(type.FindMembers(memberTypes, bindingFlags, null, null)); Type baseType = type.BaseType; while (baseType != null && baseType != typeof(object)) { members.AddRange(baseType.FindMembers(memberTypes, bindingFlags, null, null)); baseType = baseType.BaseType; } return(members); }
/// <summary> /// Gets the method with the given <paramref name="name"/> and matching <paramref name="bindingFlags"/> /// on the given <paramref name="type"/> where the parameter types correspond in order with the /// supplied <paramref name="parameterTypes"/>. /// </summary> /// <param name="type">The type on which to reflect.</param> /// <param name="genericTypes">Type parameters if this is a generic method.</param> /// <param name="name">The name of the method to search for. This argument must be supplied. The /// default behavior is to check for an exact, case-sensitive match. Pass <see href="Flags.ExplicitNameMatch"/> /// to include explicitly implemented interface members, <see href="Flags.PartialNameMatch"/> to locate /// by substring, and <see href="Flags.IgnoreCase"/> to ignore case.</param> /// <param name="parameterTypes">If this parameter is supplied then only methods with the same parameter signature /// will be included in the result. The default behavior is to check only for assignment compatibility, /// but this can be changed to exact matching by passing <see href="Flags.ExactBinding"/>.</param> /// <param name="bindingFlags">The <see cref="BindingFlags"/> or <see cref="Flags"/> combination used to define /// the search behavior and result filtering.</param> /// <returns>The specified method or null if no method was found. If there are multiple matches /// due to method overloading the first found match will be returned.</returns> public static MethodInfo Method(this Type type, Type[] genericTypes, string name, Type[] parameterTypes, Flags bindingFlags) { bool hasTypes = parameterTypes != null; bool hasGenericTypes = genericTypes != null && genericTypes.Length > 0; // we need to check all methods to do partial name matches or complex parameter binding bool processAll = bindingFlags.IsAnySet(Flags.PartialNameMatch | Flags.TrimExplicitlyImplemented); processAll |= hasTypes && bindingFlags.IsSet(Flags.IgnoreParameterModifiers); processAll |= hasGenericTypes; if (processAll) { //TODO: Might have to do the same polymorphic parameter type check for generics return(type.Methods(genericTypes, parameterTypes, bindingFlags, name).FirstOrDefault().MakeGeneric(genericTypes)); } //TODO: Check fasterflect cache first //TODO: Find out why we needed to call HasParameterSignature for polymorphism var result = hasTypes ? type.GetTypeInfo().GetMethods(bindingFlags).FirstOrDefault(mi => mi.Name == name && mi.HasParameterSignature(parameterTypes)) : type.GetTypeInfo().GetMethod(name, bindingFlags); if (result == null && bindingFlags.IsNotSet(Flags.DeclaredOnly)) { if (type.GetTypeInfo().BaseType != typeof(object) && type.GetTypeInfo().BaseType != null) { //TODO: Added slow polymorphic type checking //TODO: Check fasterflect cache first if (hasTypes) { return(type.GetTypeInfo().BaseType.GetTypeInfo().GetMethods(bindingFlags).FirstOrDefault(mi => mi.Name == name && mi.HasParameterSignature(parameterTypes))); } else { return(type.GetTypeInfo().BaseType.Method(name, parameterTypes, bindingFlags)); } } } bool hasSpecialFlags = bindingFlags.IsAnySet(Flags.ExcludeBackingMembers | Flags.ExcludeExplicitlyImplemented | Flags.ExcludeHiddenMembers); if (hasSpecialFlags) { var methods = new List <MethodInfo> { result }.Filter(bindingFlags); return((methods.Count > 0 ? methods[0] : null).MakeGeneric(genericTypes)); } return(result.MakeGeneric(genericTypes)); }
/// <summary> /// Sets the first field with the given <paramref name="name"/> on the given <paramref name="obj"/> object /// to the supplied <paramref name="value"/>. Returns true if a value was assigned to a field and false otherwise. /// Use the <paramref name="bindingFlags"/> parameter to limit the scope of the search. /// </summary> /// <param name="obj">The source object on which to find the field</param> /// <param name="name">The name of the field whose value should be retrieved</param> /// <param name="value">The value that should be assigned to the field</param> /// <param name="bindingFlags">A combination of Flags that define the scope of the search</param> /// <returns>True if the value was assigned to a field and false otherwise</returns> public static bool TrySetFieldValue(this object obj, string name, object value, Flags bindingFlags) { try { obj.SetFieldValue(name, value, bindingFlags); return(true); } catch (MissingFieldException) { return(false); } }
/// <summary> /// Gets all methods on the given <paramref name="type"/> that match the given lookup criteria. /// </summary> /// <param name="type">The type on which to reflect.</param> /// <param name="parameterTypes">If this parameter is supplied then only methods with the same parameter signature /// will be included in the result. The default behavior is to check only for assignment compatibility, /// but this can be changed to exact matching by passing <see href="Flags.ExactBinding"/>.</param> /// <param name="bindingFlags">The <see cref="BindingFlags"/> or <see cref="Flags"/> combination used to define /// the search behavior and result filtering.</param> /// <param name="names">The optional list of names against which to filter the result. If this parameter is /// <c>null</c> or empty no name filtering will be applied. The default behavior is to check for an exact, /// case-sensitive match. Pass <see href="Flags.ExcludeExplicitlyImplemented"/> to exclude explicitly implemented /// interface members, <see href="Flags.PartialNameMatch"/> to locate by substring, and /// <see href="Flags.IgnoreCase"/> to ignore case.</param> /// <returns>A list of all matching methods. This value will never be null.</returns> public static IList <MethodInfo> Methods(this Type type, Type[] parameterTypes, Flags bindingFlags, params string[] names) { return(type.Methods(null, parameterTypes, bindingFlags, names)); }
/// <summary> /// Gets the value of the field specified by <paramref name="name"/> and matching <paramref name="bindingFlags"/> /// on the given <paramref name="obj"/>. /// </summary> public static object GetFieldValue(this object obj, string name, Flags bindingFlags) { return(DelegateForGetFieldValue(obj.GetTypeAdjusted(), name, bindingFlags)(obj)); }
/// <summary> /// Gets all methods on the given <paramref name="type"/> that match the given lookup criteria. /// </summary> /// <param name="type">The type on which to reflect.</param> /// <param name="genericTypes">If this parameter is supplied then only methods with the same generic parameter /// signature will be included in the result. The default behavior is to check only for assignment compatibility, /// but this can be changed to exact matching by passing <see href="Flags.ExactBinding"/>.</param> /// <param name="parameterTypes">If this parameter is supplied then only methods with the same parameter signature /// will be included in the result. The default behavior is to check only for assignment compatibility, /// but this can be changed to exact matching by passing <see href="Flags.ExactBinding"/>.</param> /// <param name="bindingFlags">The <see cref="BindingFlags"/> or <see cref="Flags"/> combination used to define /// the search behavior and result filtering.</param> /// <param name="names">The optional list of names against which to filter the result. If this parameter is /// <c>null</c> or empty no name filtering will be applied. The default behavior is to check for an exact, /// case-sensitive match. Pass <see href="Flags.ExcludeExplicitlyImplemented"/> to exclude explicitly implemented /// interface members, <see href="Flags.PartialNameMatch"/> to locate by substring, and /// <see href="Flags.IgnoreCase"/> to ignore case.</param> /// <returns>A list of all matching methods. This value will never be null.</returns> public static IList <MethodInfo> Methods(this Type type, Type[] genericTypes, Type[] parameterTypes, Flags bindingFlags, params string[] names) { if (type == null || type == typeof(object)) { return(new MethodInfo[0]); } bool recurse = bindingFlags.IsNotSet(Flags.DeclaredOnly); bool hasNames = names != null && names.Length > 0; bool hasTypes = parameterTypes != null; bool hasGenericTypes = genericTypes != null && genericTypes.Length > 0; bool hasSpecialFlags = bindingFlags.IsAnySet(Flags.ExcludeBackingMembers | Flags.ExcludeExplicitlyImplemented | Flags.ExcludeHiddenMembers); if (!recurse && !hasNames && !hasTypes && !hasSpecialFlags) { return(type.GetTypeInfo().GetMethods(bindingFlags) ?? new MethodInfo[0]); } var methods = GetMethods(type, bindingFlags); methods = hasNames ? methods.Filter(bindingFlags, names) : methods; methods = hasGenericTypes ? methods.Filter(genericTypes) : methods; methods = hasTypes ? methods.Filter(bindingFlags, parameterTypes) : methods; methods = hasSpecialFlags ? methods.Filter(bindingFlags) : methods; return(methods); }
/// <summary> /// Creates a delegate which can get the value of the property <param name="propInfo"/> matching the /// specified <param name="bindingFlags" />. /// </summary> public static MemberGetter DelegateForGetPropertyValue( this PropertyInfo propInfo, Flags bindingFlags ) { return (MemberGetter) new MemberGetEmitter( propInfo, bindingFlags ).GetDelegate(); }
/// <summary> /// Returns true if all values in the given <paramref name="mask"/> are set in the current Flags instance. /// </summary> public bool IsSet(Flags mask) { return((flags & mask) == mask); }