Exemple #1
0
        public void GetMetadata_GetsMetadata()
        {
            var commandParameterAttribute = new CommandParameterAttribute(
                0,
                "Arg0",
                typeof(Resources),
                "TestResource")
            {
                Required     = false,
                DefaultValue = "Default"
            };
            var targetProperty = typeof(CommandStub)
                                 .GetProperty(nameof(CommandStub.StringProperty));

            var commandParameterMetadata = commandParameterAttribute.GetMetadata(targetProperty);

            Assert.That(commandParameterMetadata.Index, Is.EqualTo(0));
            Assert.That(commandParameterMetadata.Name, Is.EqualTo("Arg0"));
            Assert.That(commandParameterMetadata.HelpText, Is.EqualTo("This is a test resource."));
            Assert.That(commandParameterMetadata.Required, Is.False);
            Assert.That(commandParameterMetadata.DefaultValue, Is.EqualTo("Default"));
            Assert.That(commandParameterMetadata.Converter, Is.Not.Null);
            Assert.That(commandParameterMetadata.Converter, Is.TypeOf <DefaultArgumentConverter>());
            Assert.That(commandParameterMetadata.PropertyInfo, Is.EqualTo(targetProperty));
        }
Exemple #2
0
        /// <summary>
        /// 获得存储过程参数
        /// </summary>
        /// <returns></returns>
        public IDbParms GetParameters()
        {
            SqlParameterProvider parameters = new SqlParameterProvider();

            var properties = this.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);

            foreach (var p in properties)
            {
                CommandParameterAttribute attr = (CommandParameterAttribute)p.GetCustomAttributes(typeof(CommandParameterAttribute), false).FirstOrDefault();
                if (attr == null)
                {
                    continue;
                }

                string SPName = attr.SPName;
                if (String.IsNullOrWhiteSpace(SPName))
                {
                    SPName = p.Name;
                }

                object value = p.GetValue(this, null);

                parameters.AddParameter("@" + SPName, attr.DbType, attr.Size, value, attr.Direction);
            }

            return(parameters);
        }
Exemple #3
0
        /// <summary>
        /// Find a paramater's target in code (methods)
        /// </summary>
        /// <param name="commandType">the system type of the command</param>
        /// <param name="currentNeededParm">the paramater we are after</param>
        public void SeekInCode(Type commandType, CommandParameterAttribute currentNeededParm)
        {
            var validTargetTypes      = commandsAssembly.GetTypes().Where(t => t.GetInterfaces().Contains(currentNeededParm.ParameterType));
            var internalCommandString = CommandStringRemainder.ToList();

            var  parmWords = internalCommandString.Count();
            Type parm      = null;

            while (parmWords > 0)
            {
                var currentParmString = string.Join(" ", RemoveGrammaticalNiceities(internalCommandString.Take(parmWords))).ToLower();

                if (!currentNeededParm.MatchesPattern(currentParmString))
                {
                    parmWords--;
                    continue;
                }

                var validParms = validTargetTypes.Where(comm => comm.GetCustomAttributes <CommandKeywordAttribute>()
                                                        .Any(att => att.Keyword.Equals(currentParmString)));

                if (validParms.Count() > 1)
                {
                    AccessErrors.Add(string.Format("There are {0} potential targets with that name for the {1} command.", validParms.Count(), commandType.Name));

                    AccessErrors.AddRange(validParms.Select(typ => typ.Name));

                    break;
                }
                else if (validParms.Count() == 1)
                {
                    parm = validParms.First();

                    if (parm != null)
                    {
                        switch (currentNeededParm.Usage)
                        {
                        case CommandUsage.Supporting:
                            Supporting = Activator.CreateInstance(parm);
                            break;

                        case CommandUsage.Subject:
                            Subject = Activator.CreateInstance(parm);
                            break;

                        case CommandUsage.Target:
                            Target = Activator.CreateInstance(parm);
                            break;
                        }
                    }

                    CommandStringRemainder = CommandStringRemainder.Skip(parmWords);
                    return;
                }

                parmWords--;
            }
        }
Exemple #4
0
        /// <summary>
        /// Find a parameter target in backing data
        /// </summary>
        /// <typeparam name="T">the system type of the data</typeparam>
        /// <param name="commandType">the system type of the command</param>
        /// <param name="currentNeededParm">the conditions for the parameter we're after</param>
        public void SeekInBackingData <T>(Type commandType, CommandParameterAttribute currentNeededParm) where T : IData
        {
            var internalCommandString = CommandStringRemainder.ToList();

            var parmWords = internalCommandString.Count();

            while (parmWords > 0)
            {
                var currentParmString = string.Join(" ", internalCommandString.Take(parmWords));

                if (!currentNeededParm.MatchesPattern(currentParmString))
                {
                    parmWords--;
                    continue;
                }

                var validObject = default(T);

                long parmID = -1;
                if (!long.TryParse(currentParmString, out parmID))
                {
                    validObject = DataWrapper.GetOneBySharedKey <T>("Name", currentParmString);
                }
                else
                {
                    validObject = DataWrapper.GetOne <T>(parmID);
                }

                if (validObject != null && !validObject.Equals(default(T)))
                {
                    switch (currentNeededParm.Usage)
                    {
                    case CommandUsage.Supporting:
                        Supporting = validObject;
                        break;

                    case CommandUsage.Subject:
                        Subject = validObject;
                        break;

                    case CommandUsage.Target:
                        Target = validObject;
                        break;
                    }

                    CommandStringRemainder = CommandStringRemainder.Skip(parmWords);
                    return;
                }

                parmWords--;
            }
        }
        /// <summary>
        /// Ensures the given parameters follow the parameter rules
        /// </summary>
        /// <exception cref="CommandParsingException">Thrown if a parameter does not follow command parameter rules</exception>
        public void CheckParameterStructure(CommandExecutorData executor, IEnumerable<ParameterInfo> parameters)
        {
            bool optionalFound = false;
            bool unknownLengthFound = false;
            requiredArgumentCount = 0;
            Dictionary<ParameterInfo, CommandParameterAttribute> paramData = new Dictionary<ParameterInfo, CommandParameterAttribute>();

            foreach (ParameterInfo param in parameters)
            {
                CommandParameterAttribute attr = param.GetCustomAttribute<CommandParameterAttribute>();

                if (attr == null)
                {
                    attr = new CommandParameterAttribute(param.IsOptional);
                }

                paramData.Add(param, attr);

                if (optionalFound && !attr.Optional)
                {
                    throw new CommandParsingException(
                        ParserFailReason.InvalidParameter,
                        $"Parameter '{param.Name}' is required, but follows an optional parameter."
                    );
                }

                if (unknownLengthFound)
                {
                    throw new CommandParsingException(
                        ParserFailReason.InvalidParameter,
                        $"Parameter '{param.Name}' follows an unknown-length parameter."
                    );
                }

                if (attr.Optional)
                {
                    optionalFound = true;
                }
                if (attr.Repetitions < 1)
                {
                    unknownLengthFound = true;
                    requiredArgumentCount = -1;
                }
                if (!attr.Optional)
                {
                    requiredArgumentCount += attr.Repetitions;
                }
            }

            executor.ParameterData = paramData;
        }
Exemple #6
0
        public void DisplayDescription(string cmd)
        {
            if (string.IsNullOrEmpty(cmd))
            {
                return;
            }

            cmd = cmd.ToLower();

            if (CommandsList.ContainsKey(cmd) == false)
            {
                log.ErrorFormat("The command of '{0}' is not exists.", cmd);
                return;
            }

            ICommand command = CommandsList[cmd];

            object[] attrs = command.GetType().GetCustomAttributes(typeof(CommandAttribute), false);

            if (attrs.Length > 0)
            {
                CommandAttribute ca = attrs[0] as CommandAttribute;

                if (!string.IsNullOrEmpty(ca.Description))
                {
                    WriteLine(0, ca.Cmd + ": ", ca.Cmd.Length + 2, ca.Description);
                }

                if (!string.IsNullOrEmpty(ca.Usage))
                {
                    WriteLine(0, "用法:", 0, ca.Usage + "\r\n");
                }
            }

            attrs = command.GetType().GetCustomAttributes(typeof(CommandParameterAttribute), false);

            WriteLine(4, "/?", 10, "显示帮助信息");

            for (int i = 0; i < attrs.Length; i++)
            {
                CommandParameterAttribute cpa = attrs[i] as CommandParameterAttribute;
                WriteLine(4, cpa.Key, 10, cpa.Description);
            }
            Console.WriteLine();
        }
Exemple #7
0
        public void Constructor_GetsValues()
        {
            var commandParameterAttribute = new CommandParameterAttribute(
                0,
                "Arg0",
                typeof(Resources),
                "TestResource")
            {
                Required     = false,
                DefaultValue = "Default"
            };

            Assert.That(commandParameterAttribute.Index, Is.EqualTo(0));
            Assert.That(commandParameterAttribute.Name, Is.EqualTo("Arg0"));
            Assert.That(commandParameterAttribute.HelpText, Is.EqualTo("This is a test resource."));
            Assert.That(commandParameterAttribute.Required, Is.False);
            Assert.That(commandParameterAttribute.DefaultValue, Is.EqualTo("Default"));
        }
Exemple #8
0
        /// <summary>
        /// Find a parameter target in reference data
        /// </summary>
        /// <typeparam name="T">the system type of the data</typeparam>
        /// <param name="commandType">the system type of the command</param>
        /// <param name="currentNeededParm">the conditions for the parameter we're after</param>
        public void SeekInReferenceData <T>(Type commandType, CommandParameterAttribute currentNeededParm) where T : IReferenceData
        {
            var internalCommandString = CommandStringRemainder.ToList();

            var parmWords = internalCommandString.Count();

            while (parmWords > 0)
            {
                var currentParmString = string.Join(" ", RemoveGrammaticalNiceities(internalCommandString.Take(parmWords)));

                if (!currentNeededParm.MatchesPattern(currentParmString))
                {
                    parmWords--;
                    continue;
                }

                var validObject = ReferenceWrapper.GetOne <T>(currentParmString);

                if (validObject != null && !validObject.Equals(default(T)))
                {
                    switch (currentNeededParm.Usage)
                    {
                    case CommandUsage.Supporting:
                        Supporting = validObject;
                        break;

                    case CommandUsage.Subject:
                        Subject = validObject;
                        break;

                    case CommandUsage.Target:
                        Target = validObject;
                        break;
                    }

                    CommandStringRemainder = CommandStringRemainder.Skip(parmWords);
                    return;
                }

                parmWords--;
            }
        }
        public bool Conforms(CommandParameterAttribute attr)
        {
            var name = this.IsNamed && attr.Id == this.Name;
            var index = this.IsIndexed && attr.Index == this.Index;
            var value = string.IsNullOrEmpty(attr.Value) || attr.Value == this.Value;

            var type = false;
            try
            {
                if (this.Value != null)
                {
                    var test = Convert.ChangeType(this.Value, attr.Type);
                }
                type = true;
            }
            catch (Exception)
            {
            }

            return (!IsNamed || name) && (!IsIndexed || index) && value && type;
        }
Exemple #10
0
        public bool Conforms(CommandParameterAttribute attr)
        {
            var name  = this.IsNamed && attr.Id == this.Name;
            var index = this.IsIndexed && attr.Index == this.Index;
            var value = string.IsNullOrEmpty(attr.Value) || attr.Value == this.Value;

            var type = false;

            try
            {
                if (this.Value != null)
                {
                    var test = Convert.ChangeType(this.Value, attr.Type);
                }
                type = true;
            }
            catch (Exception)
            {
            }

            return((!IsNamed || name) && (!IsIndexed || index) && value && type);
        }
Exemple #11
0
        private bool ValidateRecursive(object obj, bool throwException, int deepLevel)
        {
            const int maxDeepLevel = 100;

            // Prevent "StackOverflowException" (this should never happen)
            if (++deepLevel == maxDeepLevel)
            {
                throw new InvalidOperationException("Recursive function call exceeded the permitted deep level.");
            }

            // Validate all properties with "CommandParameterAttribute"
            foreach (var property in CommandParameterAttribute.GetOrderedProperties(obj))
            {
                // If property is value type and is not nullable, than must be set to nullable
                if (property.PropertyType.IsValueType && Nullable.GetUnderlyingType(property.PropertyType) == null)
                {
                    if (throwException)
                    {
                        throw new InvalidOperationException($"'{property.Name}' property must be nullable.");
                    }

                    return(false);
                }
            }

            // Validate all properties with attributes derived from "ValidationAttribute"
            var results = new List <ValidationResult>();

            Validator.TryValidateObject(obj, new ValidationContext(obj), results, true);

            if (results.Count > 0)
            {
                if (throwException)
                {
                    throw new ArgumentException(results[0].ToString());
                }

                return(false);
            }


            // Find all properties value with 'CommandBuilderObjectAttribute' and validate it recursively
            var properties = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

            foreach (var property in properties)
            {
                var propertyValue = property.GetValue(obj);

                if (propertyValue == null)
                {
                    continue;
                }

                if (propertyValue.GetType().GetCustomAttribute <CommandBuilderObjectAttribute>() != null)
                {
                    ValidateRecursive(propertyValue, throwException, deepLevel);
                }
            }

            return(true);
        }
        private string BuildStringRecursive(object obj, int deepLevel)
        {
            const int maxDeepLevel = 100;

            // Prevent "StackOverflowException" (this should never happen)
            if (++deepLevel == maxDeepLevel)
            {
                throw new InvalidOperationException("Recursive function call exceeded the permitted deep level.");
            }


            var finalString = new StringBuilder();

            // Loop through all properties with "CommandParameterAttribute" attribute
            foreach (var property in CommandParameterAttribute.GetOrderedProperties(obj))
            {
                // Get property value
                var propertyValue = property.GetValue(obj);

                if (propertyValue == null)
                {
                    continue;
                }

                // Check if property value can be included in final command string
                if (!CanIncludeProperty(obj, property))
                {
                    continue;
                }

                // if property value has 'CommandBuilderObjectAttribute' then build string from it recursively
                if (propertyValue.GetType().GetCustomAttribute <CommandBuilderObjectAttribute>() != null)
                {
                    var value = BuildStringRecursive(propertyValue, deepLevel);

                    if (!string.IsNullOrWhiteSpace(value))
                    {
                        finalString.Append($" {value}");
                    }

                    continue;
                }


                // Get "CommandParameterAttribute" from property
                var commandParameterAttribute = property.GetCustomAttribute <CommandParameterAttribute>();

                if (!commandParameterAttribute.RemoveWhiteSpaceBeforeValue)
                {
                    finalString.Append(" ");
                }

                var convertedPropertyValue = GetConvertedPropertyValue(obj, property);

                // If value format is set in "CommandParameterAttribute", then use it to format property value
                if (!string.IsNullOrWhiteSpace(commandParameterAttribute.Format))
                {
                    finalString.Append(string.Format(commandParameterAttribute.Format, convertedPropertyValue));
                }
                else
                {
                    finalString.Append($"{convertedPropertyValue}");
                }
            }

            return(finalString.ToString().Trim());
        }
Exemple #13
0
        /// <summary>
        /// Find a parameter target in the live world (entity)
        /// </summary>
        /// <typeparam name="T">the system type of the entity</typeparam>
        /// <param name="commandType">the system type of the command</param>
        /// <param name="currentNeededParm">the conditions for the parameter we're after</param>
        public void SeekInLiveWorldContainer <T>(Type commandType, CommandParameterAttribute currentNeededParm, Type subjectType)
        {
            //Borked it here, we found nothing viable earlier
            if (Subject == null || !((ICollection <IEntity>)Subject).Any())
            {
                return;
            }

            var subjectCollection = (ICollection <IEntity>)Subject;

            //Containers are touch range only
            var internalCommandString = CommandStringRemainder.ToList();
            var disambiguator         = -1;
            var parmWords             = internalCommandString.Count();

            while (parmWords > 0)
            {
                var currentParmString = string.Join(" ", RemoveGrammaticalNiceities(internalCommandString.Take(parmWords))).ToLower();

                //We have disambiguation here, we need to pick the first object we get back in the list
                if (Regex.IsMatch(currentParmString, LiveWorldDisambiguationSyntax))
                {
                    disambiguator     = int.Parse(currentParmString.Substring(0, currentParmString.IndexOf(".")));
                    currentParmString = currentParmString.Substring(currentParmString.IndexOf(".") + 1);
                }

                if (!currentNeededParm.MatchesPattern(currentParmString))
                {
                    parmWords--;
                    continue;
                }

                var validObjects = new List <T>();

                validObjects.AddRange(subjectCollection.Select(sbj => sbj.CurrentLocation)
                                      .Where(cl => cl.Keywords.Any(key => key.Contains(currentParmString))).Select(ent => (T)ent));

                if (validObjects.Count() > 0)
                {
                    //Skip everything up to the right guy and then take the one we want so we don't have to horribly alter the following logic flows
                    if (disambiguator > -1 && validObjects.Count() > 1)
                    {
                        validObjects = validObjects.Skip(disambiguator - 1).Take(1).ToList();
                    }

                    if (validObjects.Count() > 1)
                    {
                        AccessErrors.Add(string.Format("There are {0} potential containers with that name for the {1} command. Try using one of the following disambiguators:", validObjects.Count(), commandType.Name));

                        int iterator = 1;
                        foreach (var obj in validObjects)
                        {
                            var entityObject = (IEntity)obj;

                            AccessErrors.Add(string.Format("{0}.{1}", iterator++, entityObject.DataTemplate.Name));
                        }

                        break;
                    }
                    else if (validObjects.Count() == 1)
                    {
                        var parm = validObjects.First();

                        if (parm != null)
                        {
                            switch (currentNeededParm.Usage)
                            {
                            case CommandUsage.Supporting:
                                Supporting = parm;
                                break;

                            case CommandUsage.Subject:
                                Subject = parm;
                                break;

                            case CommandUsage.Target:
                                Target = parm;
                                break;
                            }
                        }

                        CommandStringRemainder = CommandStringRemainder.Skip(parmWords);

                        //Now try to set the subject
                        var container = (IContains)parm;

                        var validSubjects = new List <IEntity>();

                        validSubjects.AddRange(subjectCollection.Where(sbj => sbj.CurrentLocation.Equals(container)));

                        if (validSubjects.Count() > 1)
                        {
                            AccessErrors.Add(string.Format("There are {0} potential targets with that name inside {1} for the {2} command. Try using one of the following disambiguators:"
                                                           , validObjects.Count(), parmWords, commandType.Name));

                            int iterator = 1;
                            foreach (var obj in validSubjects)
                            {
                                AccessErrors.Add(string.Format("{0}.{1}", iterator++, obj.DataTemplate.Name));
                            }
                        }
                        else if (validObjects.Count() == 1)
                        {
                            Subject = validSubjects.First();
                        }

                        return;
                    }
                }

                parmWords--;
            }
        }
Exemple #14
0
        /// <summary>
        /// Find a parameter target in the live world (entity)
        /// </summary>
        /// <typeparam name="T">the system type of the entity</typeparam>
        /// <param name="commandType">the system type of the command</param>
        /// <param name="currentNeededParm">the conditions for the parameter we're after</param>
        /// <param name="hasContainer">does the command need a container to look for things in</param>
        /// <param name="seekRange">how far we can look</param>
        public void SeekInLiveWorld <T>(Type commandType, CommandParameterAttribute currentNeededParm, CommandRangeAttribute seekRange, bool hasContainer)
        {
            var internalCommandString = CommandStringRemainder.ToList();
            var disambiguator         = -1;
            var parmWords             = internalCommandString.Count();

            while (parmWords > 0)
            {
                var currentParmString = string.Join(" ", RemoveGrammaticalNiceities(internalCommandString.Take(parmWords))).ToLower();

                //We have disambiguation here, we need to pick the first object we get back in the list
                if (Regex.IsMatch(currentParmString, LiveWorldDisambiguationSyntax))
                {
                    disambiguator     = int.Parse(currentParmString.Substring(0, currentParmString.IndexOf(".")));
                    currentParmString = currentParmString.Substring(currentParmString.IndexOf(".") + 1);
                }

                if (!currentNeededParm.MatchesPattern(currentParmString))
                {
                    parmWords--;
                    continue;
                }

                var validObjects = new List <T>();

                switch (seekRange.Type)
                {
                case CommandRangeType.Self:
                    validObjects.Add((T)Actor);
                    break;

                case CommandRangeType.Touch:
                    validObjects.AddRange(Location.GetContents <T>().Where(ent => ((IEntity)ent).Keywords.Any(key => key.Contains(currentParmString))));

                    if (Actor.GetType().GetInterfaces().Any(typ => typ == typeof(IContains)))
                    {
                        validObjects.AddRange(((IContains)Actor).GetContents <T>().Where(ent => ((IEntity)ent).Keywords.Any(key => key.Contains(currentParmString))));
                    }

                    //Containers only matter for touch usage subject paramaters, actor's inventory is already handled
                    //Don't sift through another intelligence's stuff
                    //TODO: write "does entity have permission to another entity's inventories" function on IEntity
                    if (hasContainer && currentNeededParm.Usage == CommandUsage.Subject)
                    {
                        foreach (IContains thing in Location.GetContents <T>().Where(ent => ent.GetType().GetInterfaces().Any(intf => intf == typeof(IContains)) &&
                                                                                     !ent.GetType().GetInterfaces().Any(intf => intf == typeof(IMobile)) &&
                                                                                     !ent.Equals(Actor)))
                        {
                            validObjects.AddRange(thing.GetContents <T>().Where(ent => ((IEntity)ent).Keywords.Any(key => key.Contains(currentParmString))));
                        }
                    }
                    break;

                case CommandRangeType.Local:     //requires Range to be working
                    break;

                case CommandRangeType.Regional:     //requires range to be working
                    break;

                case CommandRangeType.Global:
                    validObjects.AddRange(LiveCache.GetAll <T>().Where(ent => ((IEntity)ent).Keywords.Any(key => key.Contains(currentParmString))));
                    break;
                }

                if (hasContainer && currentNeededParm.Usage == CommandUsage.Subject && validObjects.Count() > 0)
                {
                    Subject = validObjects;
                    CommandStringRemainder = CommandStringRemainder.Skip(parmWords);
                    return;
                }
                else if (validObjects.Count() > 0)
                {
                    //Skip everything up to the right guy and then take the one we want so we don't have to horribly alter the following logic flows
                    if (disambiguator > -1 && validObjects.Count() > 1)
                    {
                        validObjects = validObjects.Skip(disambiguator - 1).Take(1).ToList();
                    }

                    if (validObjects.Count() > 1)
                    {
                        AccessErrors.Add(string.Format("There are {0} potential targets with that name for the {1} command. Try using one of the following disambiguators:", validObjects.Count(), commandType.Name));

                        int iterator = 1;
                        foreach (var obj in validObjects)
                        {
                            var entityObject = (IEntity)obj;

                            AccessErrors.Add(string.Format("{0}.{1}", iterator++, entityObject.DataTemplate.Name));
                        }

                        break;
                    }
                    else if (validObjects.Count() == 1)
                    {
                        var parm = validObjects.First();

                        if (parm != null)
                        {
                            switch (currentNeededParm.Usage)
                            {
                            case CommandUsage.Supporting:
                                Supporting = parm;
                                break;

                            case CommandUsage.Subject:
                                Subject = parm;
                                break;

                            case CommandUsage.Target:
                                Target = parm;
                                break;
                            }
                        }

                        CommandStringRemainder = CommandStringRemainder.Skip(parmWords);
                        return;
                    }
                }

                parmWords--;
            }
        }