private static ArgumentDefinition CreateArgumentDescriptor( IMutableMemberInfo member, ArgumentBaseAttribute attribute, object defaultValues, ArgumentSetDefinition argSet, object fixedDestination, ArgumentDefinition containingArgument, ServiceConfigurer serviceConfigurer) { if (!member.IsReadable || !member.IsWritable) { var declaringType = member.MemberInfo.DeclaringType; throw new InvalidArgumentSetException(member, string.Format( CultureInfo.CurrentCulture, Strings.MemberNotSupported, member.MemberInfo.Name, declaringType?.Name)); } var defaultFieldValue = (defaultValues != null) ? member.GetValue(defaultValues) : null; return(new ArgumentDefinition(member, attribute, argSet, defaultValue: defaultFieldValue, fixedDestination: fixedDestination, containingArgument: containingArgument, serviceConfigurer: serviceConfigurer)); }
private static ArgumentDefinition CreateArgumentDescriptor( IMutableMemberInfo member, ArgumentBaseAttribute attribute, object defaultValues, ArgumentSetAttribute setAttribute, CommandLineParserOptions options, object fixedDestination) { if (!member.IsReadable || !member.IsWritable) { var declaringType = member.MemberInfo.DeclaringType; throw new InvalidArgumentSetException(member, string.Format( CultureInfo.CurrentCulture, Strings.MemberNotSupported, member.MemberInfo.Name, declaringType?.Name)); } var defaultFieldValue = (defaultValues != null) ? member.GetValue(defaultValues) : null; return(new ArgumentDefinition(member, attribute, setAttribute, options, defaultFieldValue, fixedDestination: fixedDestination)); }
/// <summary> /// Primary constructor. /// </summary> /// <param name="member">Field to describe.</param> /// <param name="attribute">Argument attribute on the field.</param> /// <param name="setAttribute">Attribute on the containing argument set.</param> /// <param name="options">Provides parser options.</param> /// <param name="defaultFieldValue">Default value for the field.</param> /// <param name="parentMember">Parent member under which this field sits.</param> /// <param name="fixedDestination">Optionally provides fixed parse destination object.</param> public ArgumentDefinition(IMutableMemberInfo member, ArgumentBaseAttribute attribute, ArgumentSetAttribute setAttribute, CommandLineParserOptions options, object defaultFieldValue = null, IMutableMemberInfo parentMember = null, object fixedDestination = null) { Debug.Assert(attribute != null); Debug.Assert(member != null); Member = member; ParentMember = parentMember; Attribute = attribute; _setAttribute = setAttribute; FixedDestination = fixedDestination; _isPositional = attribute is PositionalArgumentAttribute; _reporter = options?.Reporter ?? (s => { }); ArgumentType = Attribute.GetArgumentType(member.MemberType); _collectionArgType = AsCollectionType(ArgumentType); HasDefaultValue = attribute.ExplicitDefaultValue || attribute.DynamicDefaultValue; _validationAttributes = GetValidationAttributes(ArgumentType, Member); _argumentParseContext = CreateParseContext(attribute, _setAttribute, options); LongName = GetLongName(attribute, setAttribute, member.MemberInfo); ExplicitShortName = HasExplicitShortName(attribute); ShortName = GetShortName(attribute, setAttribute, member.MemberInfo); DefaultValue = GetDefaultValue(attribute, member, defaultFieldValue); var nullableBase = Nullable.GetUnderlyingType(member.MemberType); if (_collectionArgType != null) { _collectionValues = new ArrayList(); _valueType = _collectionArgType.ElementType; } else if (nullableBase != null) { // For nullable arguments, we use the wrapped type (T in // Nullable<T>) as the value type. Parsing an enum or int is the // same as parsing an enum? or int?, for example, since null can // only arise if the value was not provided at all. _valueType = Attribute.GetArgumentType(nullableBase); } else { _valueType = ArgumentType; } Debug.Assert(_valueType != null); if (Unique && !IsCollection) { throw new InvalidArgumentSetException(member, Strings.UniqueUsedOnNonCollectionArgument); } Debug.Assert(!string.IsNullOrEmpty(LongName)); }
public ArgumentDefinition(MemberInfo member, ArgumentBaseAttribute attribute, ArgumentSetDefinition argSet, object defaultValue = null, ArgumentDefinition containingArgument = null, ServiceConfigurer serviceConfigurer = null) : this(GetMutableMemberInfo(member), attribute, argSet, defaultValue, /*fixedDestination=*/ null, containingArgument, serviceConfigurer) { }
private static ArgumentParseContext CreateParseContext(ArgumentBaseAttribute attribute, ArgumentSetAttribute setAttribute, CommandLineParserOptions options) => new ArgumentParseContext { NumberOptions = attribute.NumberOptions, AllowEmpty = attribute.AllowEmpty, FileSystemReader = options.FileSystemReader, ParserContext = options.Context, CaseSensitive = setAttribute.CaseSensitive };
/// <summary> /// Internal constructor. /// </summary> /// <param name="member">Field to describe.</param> /// <param name="attribute">Argument attribute on the field.</param> /// <param name="argSet">Argument set containing this argument.</param> /// <param name="defaultValue">Default value for the field.</param> /// <param name="fixedDestination">Optionally provides fixed parse destination object.</param> /// <param name="containingArgument">Optionally provides a reference /// to the definition of the argument that "contains" these arguments. /// </param> /// <param name="serviceConfigurer">Optionally provides a service configurer.</param> internal ArgumentDefinition(IMutableMemberInfo member, ArgumentBaseAttribute attribute, ArgumentSetDefinition argSet, object defaultValue = null, object fixedDestination = null, ArgumentDefinition containingArgument = null, ServiceConfigurer serviceConfigurer = null) { Member = member ?? throw new ArgumentNullException(nameof(member)); Attribute = attribute ?? throw new ArgumentNullException(nameof(attribute)); ContainingSet = argSet ?? throw new ArgumentNullException(nameof(argSet)); ContainingArgument = containingArgument; FixedDestination = fixedDestination; IsPositional = attribute is PositionalArgumentAttribute; ArgumentType = GetArgumentType(Attribute, member, member.MemberType, serviceConfigurer); CollectionArgumentType = AsCollectionType(ArgumentType); HasDefaultValue = attribute.ExplicitDefaultValue || attribute.DynamicDefaultValue; ValidationAttributes = GetValidationAttributes(ArgumentType, Member); LongName = GetLongName(attribute, argSet.Attribute, member.MemberInfo); ExplicitShortName = HasExplicitShortName(attribute); ShortName = GetShortNameOrNull(attribute, argSet.Attribute, member.MemberInfo); DefaultValue = GetDefaultValue(attribute, member, defaultValue); var nullableBase = Nullable.GetUnderlyingType(member.MemberType); if (CollectionArgumentType != null) { ValueType = CollectionArgumentType.ElementType; } else if (nullableBase != null) { // For nullable arguments, we use the wrapped type (T in // Nullable<T>) as the value type. Parsing an enum or int is the // same as parsing an enum? or int?, for example, since null can // only arise if the value was not provided at all. ValueType = GetArgumentType(Attribute, member, nullableBase, serviceConfigurer); } else { ValueType = ArgumentType; } Debug.Assert(ValueType != null); if (Unique && !IsCollection) { throw new InvalidArgumentSetException(member, Strings.UniqueUsedOnNonCollectionArgument); } Debug.Assert(!string.IsNullOrEmpty(LongName)); }
private static string GetLongName(ArgumentBaseAttribute attribute, ArgumentSetAttribute argSetAttribute, MemberInfo member) { if (attribute.LongName != null) { return(attribute.LongName); } var longName = member.Name; if (argSetAttribute.NameGenerationFlags.HasFlag(ArgumentNameGenerationFlags.GenerateHyphenatedLowerCaseLongNames)) { longName = longName.ToHyphenatedLowerCase(); } return(longName); }
private static object GetDefaultValue(ArgumentBaseAttribute attribute, IMutableMemberInfo member, object defaultFieldValue) { object value; if (attribute.DynamicDefaultValue) { value = defaultFieldValue; } else if (attribute.ExplicitDefaultValue) { value = attribute.DefaultValue; } else { try { // N.B. This will fail if it's a reflection-only type. value = member.MemberType.GetDefaultValue(); } catch (InvalidOperationException) { value = null; } } // Validate the value's type. if (value != null && !member.MemberType.GetTypeInfo().IsAssignableFrom(value.GetType())) { // See if it's implicitly convertible. if (!member.MemberType.IsImplicitlyConvertibleFrom(value)) { throw new InvalidArgumentSetException(member, string.Format( CultureInfo.CurrentCulture, Strings.DefaultValueIsOfWrongType, member.MemberInfo.Name, value.GetType().Name, member.MemberType.Name)); } } return(value); }
private static string GetShortNameOrNull(ArgumentBaseAttribute attribute, ArgumentSetAttribute argSetAttribute, MemberInfo member) { if (attribute is PositionalArgumentAttribute) { return(null); } if (HasExplicitShortName(attribute)) { var namedAttribute = (NamedArgumentAttribute)attribute; return(namedAttribute.ShortName.Length == 0 ? null : namedAttribute.ShortName); } var longName = GetLongName(attribute, argSetAttribute, member); var shortName = longName.Substring(0, 1); if (argSetAttribute.NameGenerationFlags.HasFlag(ArgumentNameGenerationFlags.PreferLowerCaseForShortNames)) { shortName = shortName.ToLower(); } return(shortName); }
/// <summary> /// Retrieves the <see cref="IArgumentType"/> type for the provided type. /// </summary> /// <param name="attrib">The argument attribute to use.</param> /// <param name="memberInfo">Member info for the argument.</param> /// <param name="type">The type to look up.</param> /// <param name="configurer">Optionally provides service configurer.</param> /// <returns>The found type.</returns> private static IArgumentType GetArgumentType(ArgumentBaseAttribute attrib, IMutableMemberInfo memberInfo, Type type, ServiceConfigurer configurer) { // First try to retrieve the default IArgumentType implementation // for this type, but don't fail if we can't find one. Types.ArgumentType.TryGetType(type, out IArgumentType argType); // If we don't have any overrides, then we already have the // implementation we'll need (or it doesn't exist). if (attrib.ArgumentType == null && attrib.Parser == null && attrib.Formatter == null && attrib.Completer == null) { if (argType == null) { throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, Strings.TypeNotSupported, type.Name)); } return(argType); } var serviceCollection = new ServiceCollection(); configurer?.Invoke(serviceCollection); serviceCollection.AddSingleton <Type>(type); serviceCollection.AddSingleton <IMutableMemberInfo>(memberInfo); if (attrib.Parser != null) { serviceCollection.AddTransient(typeof(IStringParser), attrib.Parser); } if (attrib.Formatter != null) { serviceCollection.AddTransient(typeof(IObjectFormatter), attrib.Formatter); } if (attrib.Completer != null) { serviceCollection.AddTransient(typeof(IStringCompleter), attrib.Completer); } if (attrib.ArgumentType != null) { if (argType != null) { serviceCollection.AddSingleton <IArgumentType>(argType); } serviceCollection.AddTransient(typeof(object), attrib.ArgumentType); argType = (IArgumentType)serviceCollection .BuildServiceProvider() .GetService <object>(); } if (argType == null) { throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, Strings.TypeNotSupported, type.Name)); } serviceCollection.AddSingleton <IArgumentType>(argType); if (attrib.Parser == null && attrib.Formatter == null && attrib.Completer == null) { return(argType); } var provider = serviceCollection.BuildServiceProvider(); var parser = provider.GetService <IStringParser>(); var formatter = provider.GetService <IObjectFormatter>(); var completer = provider.GetService <IStringCompleter>(); return(new ArgumentTypeExtension(argType, parser, formatter, completer)); }
private static bool HasExplicitShortName(ArgumentBaseAttribute attribute) { var argAttrib = attribute as NamedArgumentAttribute; return(argAttrib?.ShortName != null); }
private ArgumentDefinition DefineArg(ArgumentSetDefinition set, ArgumentBaseAttribute argAttrib) => new ArgumentDefinition( typeof(TestArgumentSet).GetProperty(nameof(TestArgumentSet.SomeProperty)), argAttrib, set);