/// <summary>
        /// Gets the members (fields, properties, constructors, methods, and events) of the specified type,
        /// with various options to control the scope of members included and optionally order the members.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="memberRelationships">OPTIONAL value that scopes the search for members based on their relationship to <paramref name="type"/>.  DEFAULT is to include the members declared in or inherited by the specified type.</param>
        /// <param name="memberOwners">OPTIONAL value that scopes the search for members based on who owns the member.  DEFAULT is to include members owned by an object or owned by the type itself.</param>
        /// <param name="memberAccessModifiers">OPTIONAL value that scopes the search for members based on access modifiers.  DEFAULT is to include members having any supported access modifier.</param>
        /// <param name="memberKinds">OPTIONAL value that scopes the search for members based on the kind of member.  DEFAULT is to include all kinds of members.</param>
        /// <param name="memberMutability">OPTIONAL value that scopes the search for members based on mutability.  DEFAULT is to include members where mutability is not applicable and where applicable, include members with any kind of mutability.</param>
        /// <param name="memberAttributes">OPTIONAL value that scopes the search for members based on the presence or absence of certain attributes on those members.  DEFAULT is to include members that are not compiler generated.</param>
        /// <param name="orderMembersBy">OPTIONAL value that specifies how to the members.  DEFAULT is return the members in no particular order.</param>
        /// <returns>
        /// The members in the specified order.
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref name="type"/> is null.</exception>
        public static IReadOnlyList <MemberInfo> GetMembersFiltered(
            this Type type,
            MemberRelationships memberRelationships = MemberRelationships.DeclaredOrInherited,
            MemberOwners memberOwners = MemberOwners.All,
            MemberAccessModifiers memberAccessModifiers = MemberAccessModifiers.All,
            MemberKinds memberKinds           = MemberKinds.All,
            MemberMutability memberMutability = MemberMutability.All,
            MemberAttributes memberAttributes = MemberAttributes.NotCompilerGenerated,
            OrderMembersBy orderMembersBy     = OrderMembersBy.None)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            var result = type
                         .GetMembersHavingRelationshipsAndOwners(memberRelationships, memberOwners)
                         .FilterMembersHavingKinds(memberKinds)
                         .FilterMembersHavingAccessModifiers(memberAccessModifiers)
                         .FilterMembersHavingMutability(memberMutability)
                         .FilterMembersHavingAttributes(memberAttributes)
                         .OrderMembers(type, orderMembersBy);

            return(result);
        }
        /// <summary>
        /// Determines if a type has a method of the specified method name.
        /// </summary>
        /// <param name="type">The type to check.</param>
        /// <param name="methodName">The name of the method to check for.</param>
        /// <param name="memberRelationships">OPTIONAL value that scopes the search for members based on their relationship to <paramref name="type"/>.  DEFAULT is to include the members declared in or inherited by the specified type.</param>
        /// <param name="memberOwners">OPTIONAL value that scopes the search for members based on who owns the member.  DEFAULT is to include members owned by an object or owned by the type itself.</param>
        /// <param name="memberAccessModifiers">OPTIONAL value that scopes the search for members based on access modifiers.  DEFAULT is to include members having any supported access modifier.</param>
        /// <param name="memberAttributes">OPTIONAL value that scopes the search for members based on the presence or absence of certain attributes on those members.  DEFAULT is to include members that are not compiler generated.</param>
        /// <returns>
        /// true if the type has a method of the specified method name, false if not.
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref name="type"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="methodName"/> is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="methodName"/> is whitespace.</exception>
        public static bool HasMethod(
            this Type type,
            string methodName,
            MemberRelationships memberRelationships = MemberRelationships.DeclaredOrInherited,
            MemberOwners memberOwners = MemberOwners.All,
            MemberAccessModifiers memberAccessModifiers = MemberAccessModifiers.All,
            MemberAttributes memberAttributes           = MemberAttributes.NotCompilerGenerated)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (methodName == null)
            {
                throw new ArgumentNullException(nameof(methodName));
            }

            if (string.IsNullOrWhiteSpace(methodName))
            {
                throw new ArgumentException(Invariant($"{nameof(methodName)} is white space."));
            }

            var methods = type
                          // ReSharper disable once RedundantArgumentDefaultValue
                          .GetMethodsFiltered(memberRelationships, memberOwners, memberAccessModifiers, memberAttributes, OrderMembersBy.None)
                          .Where(_ => _.Name == methodName)
                          .ToList();

            var result = methods.Any();

            return(result);
        }
Exemple #3
0
        /// <summary>
        /// Gets the <see cref="FieldInfo"/> for the specified field.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="fieldName">The name of the field.</param>
        /// <param name="memberRelationships">OPTIONAL value that scopes the search for members based on their relationship to <paramref name="type"/>.  DEFAULT is to include the members declared in or inherited by the specified type.</param>
        /// <param name="memberOwners">OPTIONAL value that scopes the search for members based on who owns the member.  DEFAULT is to include members owned by an object or owned by the type itself.</param>
        /// <param name="memberAccessModifiers">OPTIONAL value that scopes the search for members based on access modifiers.  DEFAULT is to include members having any supported access modifier.</param>
        /// <param name="memberMutability">OPTIONAL value that scopes the search for members based on mutability.  DEFAULT is to include members where mutability is not applicable and where applicable, include members with any kind of mutability.</param>
        /// <param name="memberAttributes">OPTIONAL value that scopes the search for members based on the presence or absence of certain attributes on those members.  DEFAULT is to include members that are not compiler generated.</param>
        /// <param name="throwIfNotFound">OPTIONAL value indicating whether to throw if no fields are found.  DEFAULT is to throw..</param>
        /// <returns>
        /// The <see cref="FieldInfo"/> or null if no fields are found and <paramref name="throwIfNotFound"/> is false.
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref name="type"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="fieldName"/> is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="fieldName"/> is whitespace.</exception>
        /// <exception cref="ArgumentException">There is no field named <paramref name="fieldName"/> on the object type using the specified binding constraints and <paramref name="throwIfNotFound"/> is true.</exception>
        /// <exception cref="ArgumentException">There is more than one field named <paramref name="fieldName"/> on the object type using the specified binding constraints.</exception>
        public static FieldInfo GetFieldFiltered(
            this Type type,
            string fieldName,
            MemberRelationships memberRelationships = MemberRelationships.DeclaredOrInherited,
            MemberOwners memberOwners = MemberOwners.All,
            MemberAccessModifiers memberAccessModifiers = MemberAccessModifiers.All,
            MemberMutability memberMutability           = MemberMutability.All,
            MemberAttributes memberAttributes           = MemberAttributes.NotCompilerGenerated,
            bool throwIfNotFound = true)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (fieldName == null)
            {
                throw new ArgumentNullException(nameof(fieldName));
            }

            if (string.IsNullOrWhiteSpace(fieldName))
            {
                throw new ArgumentException(Invariant($"{nameof(fieldName)} is white space."));
            }

            var fields = type
                         // ReSharper disable once RedundantArgumentDefaultValue
                         .GetFieldsFiltered(memberRelationships, memberOwners, memberAccessModifiers, memberMutability, memberAttributes, OrderMembersBy.None)
                         .Where(_ => _.Name == fieldName)
                         .ToList();

            FieldInfo result;

            if (!fields.Any())
            {
                if (throwIfNotFound)
                {
                    throw new ArgumentException(Invariant($"There is no field named '{fieldName}' on type '{type.ToStringReadable()}', using the specified binding constraints."));
                }
                else
                {
                    result = null;
                }
            }
            else if (fields.Count > 1)
            {
                throw new ArgumentException(Invariant($"There is more than one field named '{fieldName}' on type '{type.ToStringReadable()}', using the specified binding constraints."));
            }
            else
            {
                result = fields.Single();
            }

            return(result);
        }
Exemple #4
0
        /// <summary>
        /// Gets the value of a field on a static type.
        /// </summary>
        /// <param name="type">The type that contains the field.</param>
        /// <param name="fieldName">The name of the field.</param>
        /// <param name="memberRelationships">OPTIONAL value that scopes the search for members based on their relationship to <paramref name="type"/>.  DEFAULT is to include the members declared in or inherited by the specified type.</param>
        /// <param name="memberAccessModifiers">OPTIONAL value that scopes the search for members based on access modifiers.  DEFAULT is to include members having any supported access modifier.</param>
        /// <param name="memberMutability">OPTIONAL value that scopes the search for members based on mutability.  DEFAULT is to include members where mutability is not applicable and where applicable, include members with any kind of mutability.</param>
        /// <param name="memberAttributes">OPTIONAL value that scopes the search for members based on the presence or absence of certain attributes on those members.  DEFAULT is to include members that are not compiler generated.</param>
        /// <returns>
        /// The value of the field.
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref name="type"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="fieldName"/> is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="fieldName"/> is whitespace.</exception>
        /// <exception cref="ArgumentException">There is no field named <paramref name="fieldName"/> on type <paramref name="type"/> using the specified binding constraints.</exception>
        /// <exception cref="ArgumentException">There is more than one field named <paramref name="fieldName"/> on type <paramref name="type"/> using the specified binding constraints.</exception>
        /// <exception cref="ArgumentException">The field does not have a get method.</exception>
        public static object GetStaticFieldValue(
            this Type type,
            string fieldName,
            MemberRelationships memberRelationships     = MemberRelationships.DeclaredOrInherited,
            MemberAccessModifiers memberAccessModifiers = MemberAccessModifiers.All,
            MemberMutability memberMutability           = MemberMutability.All,
            MemberAttributes memberAttributes           = MemberAttributes.NotCompilerGenerated)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            var fieldInfo = type.GetFieldFiltered(fieldName, memberRelationships, MemberOwners.Static, memberAccessModifiers, memberMutability, memberAttributes);

            var result = fieldInfo.GetValue(null);

            return(result);
        }
        /// <summary>
        /// Gets the methods of the specified type,
        /// with various options to control the scope of methods included and optionally order the methods.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="memberRelationships">OPTIONAL value that scopes the search for members based on their relationship to <paramref name="type"/>.  DEFAULT is to include the members declared in or inherited by the specified type.</param>
        /// <param name="memberOwners">OPTIONAL value that scopes the search for members based on who owns the member.  DEFAULT is to include members owned by an object or owned by the type itself.</param>
        /// <param name="memberAccessModifiers">OPTIONAL value that scopes the search for members based on access modifiers.  DEFAULT is to include members having any supported access modifier.</param>
        /// <param name="memberAttributes">OPTIONAL value that scopes the search for members based on the presence or absence of certain attributes on those members.  DEFAULT is to include members that are not compiler generated.</param>
        /// <param name="orderMembersBy">OPTIONAL value that specifies how to the members.  DEFAULT is return the members in no particular order.</param>
        /// <returns>
        /// The methods in the specified order.
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref name="type"/> is null.</exception>
        public static IReadOnlyList <MethodInfo> GetMethodsFiltered(
            this Type type,
            MemberRelationships memberRelationships = MemberRelationships.DeclaredOrInherited,
            MemberOwners memberOwners = MemberOwners.All,
            MemberAccessModifiers memberAccessModifiers = MemberAccessModifiers.All,
            MemberAttributes memberAttributes           = MemberAttributes.NotCompilerGenerated,
            OrderMembersBy orderMembersBy = OrderMembersBy.None)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            var result = type
                         .GetMembersFiltered(memberRelationships, memberOwners, memberAccessModifiers, MemberKinds.Method, MemberMutability.All, memberAttributes, orderMembersBy)
                         .Cast <MethodInfo>()
                         .ToList();

            return(result);
        }
Exemple #6
0
        /// <summary>
        /// Sets a static field's value.
        /// </summary>
        /// <param name="type">The type that contains the field.</param>
        /// <param name="fieldName">The name of the field.</param>
        /// <param name="value">The value to set the field to.</param>
        /// <param name="memberRelationships">OPTIONAL value that scopes the search for members based on their relationship to <paramref name="type"/>.  DEFAULT is to include the members declared in or inherited by the specified type.</param>
        /// <param name="memberAccessModifiers">OPTIONAL value that scopes the search for members based on access modifiers.  DEFAULT is to include members having any supported access modifier.</param>
        /// <param name="memberMutability">OPTIONAL value that scopes the search for members based on mutability.  DEFAULT is to include members where mutability is not applicable and where applicable, include members with any kind of mutability.</param>
        /// <param name="memberAttributes">OPTIONAL value that scopes the search for members based on the presence or absence of certain attributes on those members.  DEFAULT is to include members that are not compiler generated.</param>
        /// <exception cref="ArgumentNullException"><paramref name="type"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="fieldName"/> is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="fieldName"/> is whitespace.</exception>
        /// <exception cref="ArgumentException">There is no field named <paramref name="fieldName"/> on type <paramref name="type"/> using the specified binding constraints.</exception>
        /// <exception cref="ArgumentException">There is more than one field named <paramref name="fieldName"/> on type <paramref name="type"/> using the specified binding constraints.</exception>
        /// <exception cref="InvalidCastException">Unable to assign null to the field's type.</exception>
        /// <exception cref="InvalidCastException">Unable to assign <paramref name="value"/> type to the field's type.</exception>
        public static void SetStaticFieldValue(
            this Type type,
            string fieldName,
            object value,
            MemberRelationships memberRelationships     = MemberRelationships.DeclaredOrInherited,
            MemberAccessModifiers memberAccessModifiers = MemberAccessModifiers.All,
            MemberMutability memberMutability           = MemberMutability.All,
            MemberAttributes memberAttributes           = MemberAttributes.NotCompilerGenerated)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            var fieldInfo = type.GetFieldFiltered(fieldName, memberRelationships, MemberOwners.Static, memberAccessModifiers, memberMutability, memberAttributes);

            value.ThrowIfNotAssignableTo(fieldInfo);

            fieldInfo.SetValue(null, value);
        }
Exemple #7
0
        /// <summary>
        /// Gets the value of a property.
        /// </summary>
        /// <param name="item">The object.</param>
        /// <param name="propertyName">The name of the property.</param>
        /// <param name="memberRelationships">OPTIONAL value that scopes the search for members based on their relationship to the <paramref name="item"/> Type.  DEFAULT is to include the members declared in or inherited by the specified type.</param>
        /// <param name="memberOwners">OPTIONAL value that scopes the search for members based on who owns the member.  DEFAULT is to include members owned by an object or owned by the type itself.</param>
        /// <param name="memberAccessModifiers">OPTIONAL value that scopes the search for members based on access modifiers.  DEFAULT is to include members having any supported access modifier.</param>
        /// <param name="memberMutability">OPTIONAL value that scopes the search for members based on mutability.  DEFAULT is to include members where mutability is not applicable and where applicable, include members with any kind of mutability.</param>
        /// <param name="memberAttributes">OPTIONAL value that scopes the search for members based on the presence or absence of certain attributes on those members.  DEFAULT is to include members that are not compiler generated.</param>
        /// <returns>
        /// The value of the property.
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref name="item"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="propertyName"/> is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="propertyName"/> is whitespace.</exception>
        /// <exception cref="ArgumentException">There is no property named <paramref name="propertyName"/> on the object type using the specified binding constraints.</exception>
        /// <exception cref="ArgumentException">There is more than one property named <paramref name="propertyName"/> on the object type using the specified binding constraints.</exception>
        /// <exception cref="ArgumentException">The property does not have a get method.</exception>
        public static object GetPropertyValue(
            this object item,
            string propertyName,
            MemberRelationships memberRelationships = MemberRelationships.DeclaredOrInherited,
            MemberOwners memberOwners = MemberOwners.All,
            MemberAccessModifiers memberAccessModifiers = MemberAccessModifiers.All,
            MemberMutability memberMutability           = MemberMutability.All,
            MemberAttributes memberAttributes           = MemberAttributes.NotCompilerGenerated)
        {
            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }

            var propertyInfo = item.GetType().GetPropertyFiltered(propertyName, memberRelationships, memberOwners, memberAccessModifiers, memberMutability, memberAttributes);

            var result = propertyInfo.GetValue(item);

            return(result);
        }
Exemple #8
0
        /// <summary>
        /// Sets a property's value.
        /// </summary>
        /// <param name="item">The object.</param>
        /// <param name="propertyName">The name of the property.</param>
        /// <param name="value">The value to set the property to.</param>
        /// <param name="memberRelationships">OPTIONAL value that scopes the search for members based on their relationship to the <paramref name="item"/> Type.  DEFAULT is to include the members declared in or inherited by the specified type.</param>
        /// <param name="memberOwners">OPTIONAL value that scopes the search for members based on who owns the member.  DEFAULT is to include members owned by an object or owned by the type itself.</param>
        /// <param name="memberAccessModifiers">OPTIONAL value that scopes the search for members based on access modifiers.  DEFAULT is to include members having any supported access modifier.</param>
        /// <param name="memberMutability">OPTIONAL value that scopes the search for members based on mutability.  DEFAULT is to include members where mutability is not applicable and where applicable, include members with any kind of mutability.</param>
        /// <param name="memberAttributes">OPTIONAL value that scopes the search for members based on the presence or absence of certain attributes on those members.  DEFAULT is to include members that are not compiler generated.</param>
        /// <exception cref="ArgumentNullException"><paramref name="item"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="propertyName"/> is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="propertyName"/> is whitespace.</exception>
        /// <exception cref="ArgumentException">There is no property named <paramref name="propertyName"/> on the object type using the specified binding constraints.</exception>
        /// <exception cref="ArgumentException">There is more than one property named <paramref name="propertyName"/> on the object type using the specified binding constraints.</exception>
        /// <exception cref="InvalidCastException">Unable to assign null to the property's type.</exception>
        /// <exception cref="InvalidCastException">Unable to assign <paramref name="value"/> type to the property's type.</exception>
        public static void SetPropertyValue(
            this object item,
            string propertyName,
            object value,
            MemberRelationships memberRelationships = MemberRelationships.DeclaredOrInherited,
            MemberOwners memberOwners = MemberOwners.All,
            MemberAccessModifiers memberAccessModifiers = MemberAccessModifiers.All,
            MemberMutability memberMutability           = MemberMutability.All,
            MemberAttributes memberAttributes           = MemberAttributes.NotCompilerGenerated)
        {
            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }

            var propertyInfo = item.GetType().GetPropertyFiltered(propertyName, memberRelationships, memberOwners, memberAccessModifiers, memberMutability, memberAttributes);

            value.ThrowIfNotAssignableTo(propertyInfo);

            propertyInfo.SetValue(item, value);
        }
Exemple #9
0
        /// <summary>
        /// Gets the value of a static property.
        /// </summary>
        /// <typeparam name="T">The type of the property.</typeparam>
        /// <param name="type">The type that contains the property.</param>
        /// <param name="propertyName">The name of the property.</param>
        /// <param name="memberRelationships">OPTIONAL value that scopes the search for members based on their relationship to <paramref name="type"/>.  DEFAULT is to include the members declared in or inherited by the specified type.</param>
        /// <param name="memberAccessModifiers">OPTIONAL value that scopes the search for members based on access modifiers.  DEFAULT is to include members having any supported access modifier.</param>
        /// <param name="memberMutability">OPTIONAL value that scopes the search for members based on mutability.  DEFAULT is to include members where mutability is not applicable and where applicable, include members with any kind of mutability.</param>
        /// <param name="memberAttributes">OPTIONAL value that scopes the search for members based on the presence or absence of certain attributes on those members.  DEFAULT is to include members that are not compiler generated.</param>
        /// <returns>
        /// The value of the property.
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref name="type"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="propertyName"/> is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="propertyName"/> is whitespace.</exception>
        /// <exception cref="ArgumentException">There is no property named <paramref name="propertyName"/> on type <paramref name="type"/> using the specified binding constraints.</exception>
        /// <exception cref="ArgumentException">There is more than one property named <paramref name="propertyName"/> on type <paramref name="type"/> using the specified binding constraints.</exception>
        /// <exception cref="ArgumentException">The property does not have a get method.</exception>
        /// <exception cref="InvalidCastException">The property is not of the specified type.</exception>
        public static T GetStaticPropertyValue <T>(
            this Type type,
            string propertyName,
            MemberRelationships memberRelationships     = MemberRelationships.DeclaredOrInherited,
            MemberAccessModifiers memberAccessModifiers = MemberAccessModifiers.All,
            MemberMutability memberMutability           = MemberMutability.All,
            MemberAttributes memberAttributes           = MemberAttributes.NotCompilerGenerated)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            var propertyInfo = type.GetPropertyFiltered(propertyName, memberRelationships, MemberOwners.Static, memberAccessModifiers, memberMutability, memberAttributes);

            var propertyValue = propertyInfo.GetValue(null);

            var result = propertyValue.CastOrThrowIfTypeMismatch <T>(propertyInfo);

            return(result);
        }
Exemple #10
0
        /// <summary>
        /// Gets the value of a field.
        /// </summary>
        /// <typeparam name="T">The type of the field.</typeparam>
        /// <param name="item">The object.</param>
        /// <param name="fieldName">The name of the field.</param>
        /// <param name="memberRelationships">OPTIONAL value that scopes the search for members based on their relationship to the <paramref name="item"/> Type.  DEFAULT is to include the members declared in or inherited by the specified type.</param>
        /// <param name="memberOwners">OPTIONAL value that scopes the search for members based on who owns the member.  DEFAULT is to include members owned by an object or owned by the type itself.</param>
        /// <param name="memberAccessModifiers">OPTIONAL value that scopes the search for members based on access modifiers.  DEFAULT is to include members having any supported access modifier.</param>
        /// <param name="memberMutability">OPTIONAL value that scopes the search for members based on mutability.  DEFAULT is to include members where mutability is not applicable and where applicable, include members with any kind of mutability.</param>
        /// <param name="memberAttributes">OPTIONAL value that scopes the search for members based on the presence or absence of certain attributes on those members.  DEFAULT is to include members that are not compiler generated.</param>
        /// <returns>
        /// The value of the field.
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref name="item"/> is null.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="fieldName"/> is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="fieldName"/> is whitespace.</exception>
        /// <exception cref="ArgumentException">There is no field named <paramref name="fieldName"/> on the object type using the specified binding constraints.</exception>
        /// <exception cref="ArgumentException">There is more than one field named <paramref name="fieldName"/> on the object type using the specified binding constraints.</exception>
        /// <exception cref="ArgumentException">The field does not have a get method.</exception>
        /// <exception cref="InvalidCastException">The field is not of the specified type.</exception>
        public static T GetFieldValue <T>(
            this object item,
            string fieldName,
            MemberRelationships memberRelationships = MemberRelationships.DeclaredOrInherited,
            MemberOwners memberOwners = MemberOwners.All,
            MemberAccessModifiers memberAccessModifiers = MemberAccessModifiers.All,
            MemberMutability memberMutability           = MemberMutability.All,
            MemberAttributes memberAttributes           = MemberAttributes.NotCompilerGenerated)
        {
            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }

            var fieldInfo = item.GetType().GetFieldFiltered(fieldName, memberRelationships, memberOwners, memberAccessModifiers, memberMutability, memberAttributes);

            var fieldValue = fieldInfo.GetValue(item);

            var result = fieldValue.CastOrThrowIfTypeMismatch <T>(fieldInfo);

            return(result);
        }
Exemple #11
0
        public static IReadOnlyCollection <ConstructorInfo> GetConstructorsMatchedToProperties(
            this Type classType,
            IReadOnlyCollection <PropertyInfo> properties,
            ConstructorsMatchedToPropertiesStrategy matchStrategy,
            MemberAccessModifiers memberAccessModifiers = MemberAccessModifiers.Public,
            MemberRelationships memberRelationships     = MemberRelationships.DeclaredInType)
        {
            if (classType == null)
            {
                throw new ArgumentNullException(nameof(classType));
            }

            if (!classType.IsClass)
            {
                throw new ArgumentException(Invariant($"{nameof(classType)} must be a class."));
            }

            if (properties == null)
            {
                throw new ArgumentNullException(nameof(properties));
            }

            if (properties.Any(_ => _ == null))
            {
                throw new ArgumentException(Invariant($"{nameof(properties)} has a null element."));
            }

            if (properties.Select(_ => _.Name).Distinct(StringComparer.OrdinalIgnoreCase).Count() != properties.Count)
            {
                throw new ArgumentException(Invariant($"{nameof(properties)} contains two or more members with the same name."));
            }

            if (matchStrategy == ConstructorsMatchedToPropertiesStrategy.Invalid)
            {
                throw new ArgumentException(Invariant($"{nameof(matchStrategy)} is {nameof(ConstructorsMatchedToPropertiesStrategy.Invalid)}."));
            }

            var constructors = classType.GetConstructorsFiltered(memberRelationships, MemberOwners.Instance, memberAccessModifiers);

            var propertyNameToPropertyTypeMap = properties.ToDictionary(p => p.Name, p => p.PropertyType, StringComparer.OrdinalIgnoreCase);

            var candidates = constructors
                             .Where(
                _ =>
            {
                var parameters = _.GetParameters();

                foreach (var parameter in parameters)
                {
                    // property matching parameter by name?
                    if (!propertyNameToPropertyTypeMap.ContainsKey(parameter.Name))
                    {
                        return(false);
                    }

                    var propertyType = propertyNameToPropertyTypeMap[parameter.Name];

                    // parameter type is assignable to property type OR vice-versa?
                    if ((!propertyType.IsAssignableFrom(parameter.ParameterType)) && (!parameter.ParameterType.IsAssignableFrom(propertyType)))
                    {
                        return(false);
                    }
                }

                return(true);
            })
                             .ToList();

            IReadOnlyCollection <ConstructorInfo> result;

            if (matchStrategy == ConstructorsMatchedToPropertiesStrategy.AllConstructorParametersHaveMatchingProperty)
            {
                result = candidates;
            }
            else if (matchStrategy == ConstructorsMatchedToPropertiesStrategy.AllConstructorParametersHaveMatchingPropertyWithNoUnmatchedProperties)
            {
                result = candidates
                         .Where(_ => _.GetParameters().Length == properties.Count)
                         .ToList();
            }
            else
            {
                throw new NotSupportedException(Invariant($"This {nameof(ConstructorsMatchedToPropertiesStrategy)} is not supported: {matchStrategy}."));
            }

            return(result);
        }
        private static IReadOnlyList <MemberInfo> GetMembersHavingRelationshipsAndOwners(
            this Type type,
            MemberRelationships memberRelationships,
            MemberOwners memberOwners)
        {
            var result = new List <MemberInfo>();

            if (memberOwners == MemberOwners.None)
            {
                // no-op; no members to add
            }
            else if (memberRelationships == MemberRelationships.None)
            {
                // no-op; no members to add
            }
            else
            {
                var baseBindingFlags = BindingFlags.Public | BindingFlags.NonPublic;

                if (memberOwners.HasFlag(MemberOwners.Instance))
                {
                    baseBindingFlags |= BindingFlags.Instance;
                }

                if (memberOwners.HasFlag(MemberOwners.Static))
                {
                    baseBindingFlags |= BindingFlags.Static;
                }

                if (memberRelationships.HasFlag(MemberRelationships.DeclaredInType))
                {
                    var declaredMembers = type.GetMembers(baseBindingFlags | BindingFlags.DeclaredOnly);

                    result.AddRange(declaredMembers);
                }

                if (memberRelationships.HasFlag(MemberRelationships.InheritedByType))
                {
                    // If we are also looking for members declared in ancestor types, then that search will
                    // return all inherited members along with any non-inherited members.
                    if (!memberRelationships.HasFlag(MemberRelationships.DeclaredInAncestorTypes))
                    {
                        var inheritedMembers = type
                                               .GetMembers(baseBindingFlags | BindingFlags.FlattenHierarchy)
                                               .Where(_ => _.DeclaringType != type)
                                               .ToList();

                        result.AddRange(inheritedMembers);
                    }
                }

                if (memberRelationships.HasFlag(MemberRelationships.DeclaredInAncestorTypes))
                {
                    var ancestorTypes = type.GetInheritancePath();

                    foreach (var ancestorType in ancestorTypes)
                    {
                        var ancestorDeclaredMembers = ancestorType.GetMembers(baseBindingFlags | BindingFlags.DeclaredOnly);

                        result.AddRange(ancestorDeclaredMembers);
                    }
                }

                if (memberRelationships.HasFlag(MemberRelationships.DeclaredInImplementedInterfaceTypes))
                {
                    var interfaceTypes = type.GetInterfaces();

                    foreach (var interfaceType in interfaceTypes)
                    {
                        var interfaceMembers = interfaceType.GetMembers(baseBindingFlags | BindingFlags.DeclaredOnly);

                        result.AddRange(interfaceMembers);
                    }
                }
            }

            return(result);
        }