private void AddValue( ArgDef def, object val )
        {
            ArgValue av = new ArgValue() { Definition = def };

            try
            {
                switch( def.ArgKind )
                {
                    case ArgDef.Kind.Bool:
                        av.Value = (bool) Convert.ChangeType( val, typeof(bool) );
                        break;
                    case ArgDef.Kind.Int:
                        av.Value = (int)  Convert.ChangeType( val, typeof(int) );
                        break;
                    case ArgDef.Kind.String:
                        av.Value = (string) val;
                        break;
                }
            }
            catch( Exception ex )
            {
                throw new ArgumentOutOfRangeException(
                    "Could not convert value for argument " + def.PropertyName,
                    ex );
            }

            dictionary[ def.PropertyName ] = av;
        }
        private void ValidateDefinitions( ArgDef def )
        {
            var scmode = SCMode;

            // Check  switch values
            if( string.IsNullOrWhiteSpace( def.ShortSwitch ) &&
                string.IsNullOrWhiteSpace( def.LongSwitch ) )
            {
                throw new ArgumentOutOfRangeException(
                    "def.ShortSwitch",
                    "ShortSwitch or LongSwitch must be set" );
            }
            if( string.IsNullOrWhiteSpace( def.ShortSwitch ) )
            {
                def.ShortSwitch = Unassigned;
            }
            if( string.IsNullOrWhiteSpace( def.LongSwitch ) )
            {
                def.LongSwitch  = Unassigned;
            }

            // Check duplications
            if( definitions.Any( (d) =>
                  (def.ShortSwitch != Unassigned &&
                   (string.Compare( def.ShortSwitch, d.ShortSwitch, scmode ) == 0 ||
                    string.Compare( def.ShortSwitch, d.LongSwitch,  scmode ) == 0)) ||
                  (def.LongSwitch != Unassigned &&
                   (string.Compare( def.ShortSwitch, d.LongSwitch, scmode ) == 0 ||
                    string.Compare( def.LongSwitch,  d.LongSwitch,  scmode ) == 0 )) ) )
            {
                string msg = string.Format( "Either {0} or {1} collides with an existing switch",
                    def.ShortSwitch, def.LongSwitch );
                throw new ArgumentOutOfRangeException( msg );
            }
            if( definitions.Any( (d) =>
                string.Compare( def.PropertyName, d.PropertyName, StringComparison.Ordinal ) == 0 ) )
            {
                string msg = string.Format( "PropertyName {0} is already defined", def.PropertyName );
                throw new ArgumentOutOfRangeException( msg );
            }

            // Only one can be 'unswitched', i.e. the final argument's implicit switch
            if( def.UnSwitched && definitions.Any( ( d ) => d.UnSwitched ) )
            {
                throw new ArgumentOutOfRangeException(
                    def.PropertyName + " cannot also be UnSwitched" );
            }

            //if( def.ArgKind == ArgDef.Kind.Bool && def.DefaultValue != null )
            //    throw new ArgumentOutOfRangeException( "Bool properties cannot override DefaultValue" );

            // Infer missing data...
            if( def.DefaultValue == null )
            {
                if( def.ArgKind == ArgDef.Kind.Bool )
                {
                    def.DefaultValue = (object) false;
                }
                else if( def.ArgKind == ArgDef.Kind.Int )
                {
                    def.DefaultValue = (object) 0;
                }
            }

            if( def.HelpText == null )
            {
                def.HelpText = "<no help available>";
            }
        }
        /// <summary>Registers a new potential command-line argument</summary>
        /// <param name="def">A command-line argument definition to add</param>
        public void Add( ArgDef  def )
        {
            ValidateDefinitions( def );

            definitions.Add( def );
        }