public static SpecificationProperty WithValue(this SpecificationProperty specProp, Maybe <object> newValue)
        {
            if (newValue == null)
            {
                throw new ArgumentNullException(nameof(newValue));
            }

            return(SpecificationProperty.Create(specProp.Specification, specProp.Property, newValue));
        }
        public static SpecificationProperty WithSpecification(this SpecificationProperty specProp, Specification newSpecification)
        {
            if (newSpecification == null)
            {
                throw new ArgumentNullException(nameof(newSpecification));
            }

            return(SpecificationProperty.Create(newSpecification, specProp.Property, specProp.Value));
        }
        public static Type GetConversionType(this SpecificationProperty specProp)
        {
            switch (specProp.Specification.TargetType)
            {
            case TargetType.Sequence:
                return(specProp.Property.PropertyType.GetTypeInfo().GetGenericArguments()
                       .SingleOrDefault()
                       .ToMaybe()
                       .FromJustOrFail(
                           new InvalidOperationException("Sequence properties should be of type IEnumerable<T>.")));

            default:
                return(specProp.Property.PropertyType);
            }
        }
示例#4
0
        private static IEnumerable <Error> SetValue <T>(this SpecificationProperty specProp, T instance, object value)
        {
            try
            {
                specProp.Property.SetValue(instance, value, null);
                return(Enumerable.Empty <Error>());
            }
            catch (TargetInvocationException e)
            {
                return(new[] { new SetValueExceptionError(specProp.Specification.FromSpecification(), e.InnerException, value) });
            }
            catch (ArgumentException e)
            {
                var argEx = new ArgumentException(InvalidAttributeConfigurationError.ErrorMessage, e);

                return(new[] { new SetValueExceptionError(specProp.Specification.FromSpecification(), argEx, value) });
            }

            catch (Exception e)
            {
                return(new[] { new SetValueExceptionError(specProp.Specification.FromSpecification(), e, value) });
            }
        }
        public static ParserResult <T> Build <T>(
            Maybe <Func <T> > factory,
            Func <IEnumerable <string>, IEnumerable <OptionSpecification>, Result <IEnumerable <Token>, Error> > tokenizer,
            IEnumerable <string> arguments,
            StringComparer nameComparer,
            bool ignoreValueCase,
            CultureInfo parsingCulture,
            bool autoHelp,
            bool autoVersion,
            IEnumerable <ErrorType> nonFatalErrors)
        {
            var typeInfo = factory.MapValueOrDefault(f => f().GetType(), typeof(T));

            var specProps = typeInfo.GetSpecifications(pi => SpecificationProperty.Create(
                                                           Specification.FromProperty(pi), pi, Maybe.Nothing <object>()))
                            .Memoize();

            var specs = from pt in specProps select pt.Specification;

            var optionSpecs = specs
                              .ThrowingValidate(SpecificationGuards.Lookup)
                              .OfType <OptionSpecification>()
                              .Memoize();

            Func <T> makeDefault = () =>
                                   typeof(T).IsMutable()
                    ? factory.MapValueOrDefault(f => f(), () => Activator.CreateInstance <T>())
                    : ReflectionHelper.CreateDefaultImmutableInstance <T>(
                (from p in specProps select p.Specification.ConversionType).ToArray());

            Func <IEnumerable <Error>, ParserResult <T> > notParsed =
                errs => new NotParsed <T>(makeDefault().GetType().ToTypeInfo(), errs);

            var argumentsList = arguments.Memoize();
            Func <ParserResult <T> > buildUp = () =>
            {
                var tokenizerResult = tokenizer(argumentsList, optionSpecs);

                var tokens = tokenizerResult.SucceededWith().Memoize();

                var partitions = TokenPartitioner.Partition(
                    tokens,
                    name => TypeLookup.FindTypeDescriptorAndSibling(name, optionSpecs, nameComparer));
                var optionsPartition = partitions.Item1.Memoize();
                var valuesPartition  = partitions.Item2.Memoize();
                var errorsPartition  = partitions.Item3.Memoize();

                var optionSpecPropsResult =
                    OptionMapper.MapValues(
                        (from pt in specProps where pt.Specification.IsOption() select pt),
                        optionsPartition,
                        (vals, type, isScalar) => TypeConverter.ChangeType(vals, type, isScalar, parsingCulture, ignoreValueCase),
                        nameComparer);

                var valueSpecPropsResult =
                    ValueMapper.MapValues(
                        (from pt in specProps where pt.Specification.IsValue() orderby((ValueSpecification)pt.Specification).Index select pt),
                        valuesPartition,
                        (vals, type, isScalar) => TypeConverter.ChangeType(vals, type, isScalar, parsingCulture, ignoreValueCase));

                var missingValueErrors = from token in errorsPartition
                                         select
                                         new MissingValueOptionError(
                    optionSpecs.Single(o => token.Text.MatchName(o.ShortName, o.LongName, nameComparer))
                    .FromOptionSpecification());

                var specPropsWithValue =
                    optionSpecPropsResult.SucceededWith().Concat(valueSpecPropsResult.SucceededWith()).Memoize();

                var setPropertyErrors = new List <Error>();

                //build the instance, determining if the type is mutable or not.
                T instance;
                if (typeInfo.IsMutable() == true)
                {
                    instance = BuildMutable(factory, specPropsWithValue, setPropertyErrors);
                }
                else
                {
                    instance = BuildImmutable(typeInfo, factory, specProps, specPropsWithValue, setPropertyErrors);
                }

                var validationErrors = specPropsWithValue.Validate(SpecificationPropertyRules.Lookup(tokens));

                var allErrors =
                    tokenizerResult.SuccessMessages()
                    .Concat(missingValueErrors)
                    .Concat(optionSpecPropsResult.SuccessMessages())
                    .Concat(valueSpecPropsResult.SuccessMessages())
                    .Concat(validationErrors)
                    .Concat(setPropertyErrors)
                    .Memoize();

                var warnings = from e in allErrors where nonFatalErrors.Contains(e.Tag) select e;

                return(allErrors.Except(warnings).ToParserResult(instance));
            };

            var preprocessorErrors = (
                argumentsList.Any()
                    ? arguments.Preprocess(PreprocessorGuards.Lookup(nameComparer, autoHelp, autoVersion))
                    : Enumerable.Empty <Error>()
                ).Memoize();

            var result = argumentsList.Any()
                ? preprocessorErrors.Any()
                    ? notParsed(preprocessorErrors)
                    : buildUp()
                : buildUp();

            return(result);
        }