public static IEnumerable <Parameter> GetParameters(this IParametrizedObject @this)
 {
     return(@this
            .GetType()
            .GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
            .Concat <MemberInfo>(@this.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static))
            .Select(fop => new { FieldOrProperty = fop, Attribute = ProcessAttributes(fop) })
            .Where(d => d.Attribute != null)
            .Select(d => CreateParameter(@this, d.FieldOrProperty, d.Attribute))
            .ToArray());
 }
 public static IEnumerable <InnerParametrizedObject> GetInnerParametrizedObjects(
     this IParametrizedObject @this)
 {
     return(@this
            .GetType()
            .GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
            .Concat <MemberInfo>(@this.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static))
            .Where(fop => !fop.GetCustomAttributes(typeof(CompilerGeneratedAttribute), true).Any())
            .Where(fop => typeof(IParametrizedObject).IsAssignableFrom(fop.GetFieldOrPropertyType()))
            .Select(fop => GetInnerParametrizedObject(@this, fop))
            .Where(po => po != null)
            .ToArray());
 }
        public static void CopyParametersFrom(this IParametrizedObject @this, IParametrizedObject other)
        {
            Contract.Requires(@this.GetType().Equals(other.GetType()));

            foreach (var parameterPair
                     in Enumerable.Zip(@this.GetParameters(), other.GetParameters(), (p1, p2) => new { P1 = p1, P2 = p2 }))
            {
                parameterPair.P1.SetValue(parameterPair.P2.GetValue());
            }
        }
        public static void CopyParametersFromWithInnerObjects(this IParametrizedObject @this, IParametrizedObject other)
        {
            Contract.Requires(@this.GetType().Equals(other.GetType()));

            @this.CopyParametersFrom(other);

            foreach (var objectPair
                     in Enumerable.Zip(@this.GetInnerParametrizedObjects(), other.GetInnerParametrizedObjects(), (o1, o2) => new { O1 = o1, O2 = o2 }))
            {
                objectPair.O1.ParametrizedObject.CopyParametersFromWithInnerObjects(objectPair.O2.ParametrizedObject);
            }

            @this.ParametersChanged();
        }
        private static string GetFieldOrPropertyTypeDescription(IParametrizedObject @this, Type type, MemberInfo fieldOrProperty)
        {
            if (fieldTypeToDescription.ContainsKey(type))
            {
                return(fieldTypeToDescription[type]);
            }

            if (type.BaseType != null && fieldTypeToDescription.ContainsKey(type.BaseType))
            {
                return(fieldTypeToDescription[type.BaseType]);
            }

            throw new InvalidOperationException("Unsupported field type: '" + type.FullName + "' used in class: '" + @this.GetType().FullName + "', field name: '" + fieldOrProperty.Name + "'");
        }
        private static Parameter CreateParameter(IParametrizedObject @this, MemberInfo fieldOrProperty, object attribute)
        {
            Parameter result = null;

            ParameterAttribute parameterAttribute = attribute as ParameterAttribute;

            Type fieldType = fieldOrProperty.GetFieldOrPropertyType();

            string typeDescription = GetFieldOrPropertyTypeDescription(@this, fieldType, fieldOrProperty);

            result = new Parameter(
                @this,
                fieldOrProperty,
                fieldType,
                parameterAttribute.MinimumValue,
                parameterAttribute.MaximumValue,
                parameterAttribute.StringType,
                parameterAttribute.Description,
                typeDescription);

            if (!result.IsString && result.StringType != StringParameterType.Unspecified)
            {
                throw new InvalidOperationException("'StringType' argument can be used only with string fields. Class: " + @this.GetType().FullName + ", field name: " + fieldOrProperty.Name);
            }

            if (!result.IsNumeric && (result.MinimumValue != null || result.MaximumValue != null))
            {
                throw new InvalidOperationException("'MinimumValue' and 'MaximumValue' arguments can be used only with numeric fields. Class: " + @this.GetType().FullName + ", field name: " + fieldOrProperty.Name);
            }

            return(result);
        }