public static void Extract(IBuildContext context, object obj)
        {
            FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
            foreach (FieldInfo field in fields)
            {
                object[] attrs = field.GetCustomAttributes(typeof(InjectContextAttribute), true);
                if (attrs.Length == 0)
                {
                    continue;
                }

                InjectContextAttribute attr = attrs[0] as InjectContextAttribute;
                if (attr == null || attr.Usage == ContextUsage.In)
                {
                    continue;
                }

                if (field.FieldType == typeof(IBuildContext))
                {
                    throw new InvalidOperationException("IBuildContext can only be used with the ContextUsage.In option.");
                }

                IContextObject contextObject = field.GetValue(obj) as IContextObject;
                if (!attr.Optional)
                {
                    context.SetContextObject(field.FieldType, contextObject);
                }
                else if (contextObject != null)
                {
                    context.SetContextObject(field.FieldType, contextObject);
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Determines if the input matches any registered scanners, and invokes the scanner callback if a match is found.
        /// This method will also invoke the <see cref="InputResultDelegate"/> callback if a scanner is found
        /// </summary>
        /// <param name="input"></param>
        /// <param name="ctx"></param>
        /// <param name="callback"></param>
        public bool ScanInput(string input, IContextObject ctx, InputResultDelegate callback)
        {
            ThrowIfDisposed();

            if (_scanners.Count == 0)
            {
                return(false);
            }

            ScannerData scanner = _scanners.FirstOrDefault(s => s.Pattern.Matches(input));

            if (scanner != null)
            {
                bool remove = false;

                object result = scanner.Callback.Invoke(ctx, input, new LightweightParser(ctx), ref remove);
                callback?.Invoke(InputResult.Scanner, result);

                if (remove)
                {
                    _scanners.Remove(scanner);
                }

                return(true);
            }

            return(false);
        }
Exemplo n.º 3
0
        private static void ExtractFields <K>(IContextContainer <K> context, IContextObject extractObj)
        {
            List <FieldInfo> fields = cachedTypeFieldDic[extractObj.GetType()][ContextUsage.Extract];

            if (fields != null && fields.Count > 0)
            {
                foreach (var field in fields)
                {
                    if (typeof(IContextContainer <>).IsAssignableFrom(field.FieldType))
                    {
                        throw new InvalidOperationException("Context can only be used with the InjectUsage.In option.");
                    }

                    var    attr  = field.GetCustomAttribute <ContextIEAttribute>();
                    object value = field.GetValue(extractObj);
                    if (!attr.Optional)
                    {
                        context.AddOrUpdate((K)attr.Key, value);
                    }
                    else if (value != null)
                    {
                        context.AddOrUpdate((K)attr.Key, value);
                    }
                }
            }
        }
Exemplo n.º 4
0
        private static void ExtractProperties <K>(IContextContainer <K> context, IContextObject extractObj)
        {
            List <PropertyInfo> properties = cachedTypePropertyDic[extractObj.GetType()][ContextUsage.Extract];

            if (properties != null && properties.Count > 0)
            {
                foreach (var property in properties)
                {
                    if (typeof(IContextContainer <>).IsAssignableFrom(property.PropertyType))
                    {
                        throw new InvalidOperationException("Context can only be used with the InjectUsage.In option.");
                    }

                    var    attr       = property.GetCustomAttribute <ContextIEAttribute>();
                    object fieldValue = property.GetValue(extractObj);
                    if (!attr.Optional)
                    {
                        context.AddOrUpdate((K)attr.Key, fieldValue);
                    }
                    else if (fieldValue != null)
                    {
                        context.AddOrUpdate((K)attr.Key, fieldValue);
                    }
                }
            }
        }
 public EvaluationContext(IContextObject ctxObject, string name = null)
 {
     ContextObjects = new List <IContextObject> {
         ctxObject
     };
     AddNamedContext(ctxObject, name);
 }
Exemplo n.º 6
0
 /// <summary>
 /// Generates a new parser that uses the given registry, args, metadata, context, and ID to run
 /// </summary>
 /// <param name="registry">Registry from which the parser will obtain <see cref="IObjectConverter"/>s</param>
 /// <param name="input">The original input string</param>
 /// <param name="additionalArgs">Any additional arguments to be added to the end of the argument list</param>
 /// <param name="metadata">CommandMetadata containing information used to parse and execute</param>
 /// <param name="exeData"><see cref="CommandExecutorData"/> containing the data required for execution</param>
 /// <param name="ctx">Context object passed to the executed command, and an <see cref="IObjectConverter"/>s that are used</param>
 /// <param name="callback">Reference to a method used as a callback when processing completes</param>
 public Parser(CommandRegistry registry,
               string input,
               IEnumerable <object> additionalArgs,
               CommandMetadata metadata,
               CommandExecutorData exeData,
               IContextObject ctx,
               InputResultDelegate callback)
     : base(registry, input, additionalArgs, metadata, exeData, ctx, callback)
 {
 }
Exemplo n.º 7
0
 /// <summary>
 /// Returns an instance of the parser that is currently registered.
 /// </summary>
 /// <param name="registry">Registry to be used by the parser</param>
 /// <param name="input">String input provided to the parser</param>
 /// <param name="args">Additional arguments to be used by the parser</param>
 /// <param name="metadata">Metadata to be used by the parser</param>
 /// <param name="exeData">CommandExecutorData to be used by the parser</param>
 /// <param name="ctx">Context to be used by the parser</param>
 /// <param name="callback">Callback method to be invoked when the parser completes</param>
 public AbstractParser GetParser(CommandRegistry registry,
                                 string input,
                                 IEnumerable <object> args,
                                 CommandMetadata metadata,
                                 CommandExecutorData exeData,
                                 IContextObject ctx,
                                 InputResultDelegate callback)
 {
     ThrowIfDisposed();
     return((AbstractParser)Activator.CreateInstance(_parser, registry, input, args, metadata, exeData, ctx, callback));
 }
Exemplo n.º 8
0
        /// <summary>
        /// Adds a command to the command queue, ready to be executed
        /// </summary>
        public void QueueInputHandling(string input, IContextObject ctx, InputResultDelegate callback)
        {
            ThrowIfDisposed();

            if (!ScanInput(input, ctx, callback))
            {
                _queue.Enqueue(new QueueData(input, callback, ctx));

                //Set the MRE so that our parser thread knows there's data
                _mre.Set();
            }
        }
Exemplo n.º 9
0
        /// <inheritdoc />
        public bool TryGetContextObject(Type type, out IContextObject contextObject)
        {
            IContextObject cachedContextObject;

            if (m_ContextObjects.TryGetValue(type, out cachedContextObject) && type.IsInstanceOfType(cachedContextObject))
            {
                contextObject = cachedContextObject;
                return(true);
            }

            contextObject = null;
            return(false);
        }
Exemplo n.º 10
0
        public static void DoRequest <RequestType, ResultType>(this IContextObject sender, RequestType request)
            where RequestType : IHas <IRequestLogic <RequestType, ResultType> >
        {
            var context = sender.Context as IHas <ICRActionLogic <RequestType> >;

            if (context != null)
            {
                context.Enter(request);
            }
            else
            {
                DefaultContext <RequestType, ResultType> .Instance.Enter(request);
            }
        }
Exemplo n.º 11
0
        public static void DoUnregister <RequestType, ResultType>(this IContextObject sender, Action <RequestType> callBackMethod)
            where RequestType : IHas <IRequestLogic <RequestType, ResultType> >
        {
            var context = sender.Context as ICRModificationLogic <RequestType>;

            if (context != null)
            {
                context.RemovePath(callBackMethod);
            }
            else
            {
                DefaultContext <RequestType, ResultType> .Instance.RemovePath(callBackMethod);
            }
        }
Exemplo n.º 12
0
        /// <summary>
        /// Creates an object of the given type, using the given arguments for construction.
        /// Converters for object types are retrieved from the given registry
        /// </summary>
        /// <param name="type"></param>
        /// <param name="arguments"></param>
        /// <param name="ctx"></param>
        /// <returns></returns>
        public static object CreateObject(Type type, object[] arguments, IContextObject ctx)
        {
            string rejectionStr;

            if (arguments == null)
            {
                rejectionStr = $"failed to create an instance of type '{type.Name}' via the default constructor.";
            }
            else
            {
                rejectionStr = $"failed to create an instance of type '{type.Name}' from arguments '{string.Join(" ", arguments)}'.";
            }

            if (type == typeof(string))
            {
                //strings get special treatment - why convert to a string when it already is one?
                return(string.Join(" ", arguments));
            }

            TypeInfo tInfo = type.GetTypeInfo();

            if (tInfo.IsValueType)
            {
                try
                {
                    //value types are converted with a TypeConverter
                    TypeConverter tc = TypeDescriptor.GetConverter(type);
                    return(tc.ConvertFromString(string.Join(" ", arguments)));
                }
                catch (Exception e)
                {
                    throw new CommandParsingException(ParserFailReason.ParsingFailed, $"TypeConverter {rejectionStr}", e);
                }
            }

            if (tInfo.IsArray)
            {
                //Arrays get their own method
                return(CreateArray(type, arguments, ctx));
            }

            try
            {
                return(Activator.CreateInstance(type, arguments));
            }
            catch (Exception e)
            {
                throw new CommandParsingException(ParserFailReason.ParsingFailed, $"Activator {rejectionStr}", e);
            }
        }
Exemplo n.º 13
0
        /// <inheritdoc />
        public void SetContextObject(IContextObject contextObject)
        {
            if (contextObject == null)
            {
                throw new ArgumentNullException("contextObject");
            }

            List <Type> types = new List <Type>(WalkAssignableTypes(contextObject));

            if (types.Count == 0)
            {
                throw new Exception($"Could not determine context object type for object of type {contextObject.GetType().FullName}");
            }
            types.ForEach(x => m_ContextObjects[x] = contextObject);
        }
Exemplo n.º 14
0
 /// <summary>
 /// Generates a new parser that uses the given registry, args, metadata, context, and ID to run
 /// </summary>
 /// <param name="registry">Registry from which the parser will obtain <see cref="IObjectConverter"/>s</param>
 /// <param name="input">The original input string</param>
 /// <param name="additionalArgs">Enumerable of objects to be parsed</param>
 /// <param name="metadata">CommandMetadata containing information used to parse and execute</param>
 /// <param name="exeData"><see cref="CommandExecutorData"/> containing the data required for execution</param>
 /// <param name="ctx">Context object passed to the executed command, and an <see cref="IObjectConverter"/>s that are used</param>
 /// <param name="callback">Reference to a method to be invoked when parsing completes</param>
 public AbstractParser(CommandRegistry registry,
                       string input,
                       IEnumerable <object> additionalArgs,
                       CommandMetadata metadata,
                       CommandExecutorData exeData,
                       IContextObject ctx,
                       InputResultDelegate callback)
 {
     Registry       = registry;
     Input          = input;
     AdditionalArgs = additionalArgs;
     Metadata       = metadata;
     ExecutorData   = exeData;
     Context        = ctx;
     Callback       = callback;
 }
Exemplo n.º 15
0
        /// <summary>
        /// 设置情景对象
        /// </summary>
        public void SetContextObject(IContextObject contextObject)
        {
            if (contextObject == null)
            {
                throw new ArgumentNullException("contextObject");
            }

            var type = contextObject.GetType();

            if (_contextObjects.ContainsKey(type))
            {
                throw new Exception($"Context object {type} is already existed.");
            }

            _contextObjects.Add(type, contextObject);
        }
Exemplo n.º 16
0
        /// <inheritdoc />
        public void SetContextObject(Type type, IContextObject contextObject)
        {
            if (contextObject == null)
            {
                throw new ArgumentNullException("contextObject");
            }

            if (!type.IsInterface)
            {
                throw new InvalidOperationException(string.Format("Passed in type '{0}' is not an interface.", type));
            }
            if (!type.IsInstanceOfType(contextObject))
            {
                throw new InvalidOperationException(string.Format("'{0}' is not of passed in type '{1}'.", contextObject.GetType(), type));
            }
            m_ContextObjects[type] = contextObject;
        }
Exemplo n.º 17
0
        /// <inheritdoc />
        public void SetContextObject(IContextObject contextObject)
        {
            if (contextObject == null)
            {
                throw new ArgumentNullException("contextObject");
            }

            var iCType = typeof(IContextObject);

            Type[] iTypes = contextObject.GetType().GetInterfaces();
            foreach (var iType in iTypes)
            {
                if (!iCType.IsAssignableFrom(iType) || iType == iCType)
                {
                    continue;
                }
                m_ContextObjects[iType] = contextObject;
            }
        }
Exemplo n.º 18
0
        /// <inheritdoc />
        public void SetContextObject <T>(IContextObject contextObject) where T : IContextObject
        {
            if (contextObject == null)
            {
                throw new ArgumentNullException("contextObject");
            }

            var type = typeof(T);

            if (!type.IsInterface)
            {
                throw new InvalidOperationException(string.Format("Passed in type '{0}' is not an interface.", type));
            }
            if (!(contextObject is T))
            {
                throw new InvalidOperationException(string.Format("'{0}' is not of passed in type '{1}'.", contextObject.GetType(), type));
            }
            m_ContextObjects[typeof(T)] = contextObject;
        }
Exemplo n.º 19
0
        private IEnumerable <Type> WalkAssignableTypes(IContextObject contextObject)
        {
            var iCType = typeof(IContextObject);

            foreach (Type t in contextObject.GetType().GetInterfaces())
            {
                if (iCType.IsAssignableFrom(t) && t != iCType)
                {
                    yield return(t);
                }
            }

            for (var current = contextObject.GetType(); current != null; current = current.BaseType)
            {
                if (iCType.IsAssignableFrom(current) && current != iCType)
                {
                    yield return(current);
                }
            }
        }
Exemplo n.º 20
0
        private static void InjectFields <K>(IContextContainer <K> context, IContextObject injectObj)
        {
            List <FieldInfo> fields = cachedTypeFieldDic[injectObj.GetType()][ContextUsage.Inject];

            if (fields != null && fields.Count > 0)
            {
                foreach (var field in fields)
                {
                    var attr = field.GetCustomAttribute <ContextIEAttribute>();

                    if (!context.TryGet((K)attr.Key, out object value))
                    {
                        if (value == null && !attr.Optional)
                        {
                            throw new ContextValueNullException(attr.Key);
                        }
                    }
                    field.SetValue(injectObj, value);
                }
            }
        }
Exemplo n.º 21
0
        public static void Inject <K>(IContextContainer <K> context, IContextObject injectObj)
        {
            if (injectObj == null || context == null)
            {
                throw new ArgumentNullException("argument is null.");
            }
            Type injectObjType = injectObj.GetType();

            if (!cachedTypeFieldDic.ContainsKey(injectObjType))
            {
                CachedFields(injectObjType);
            }

            if (!cachedTypePropertyDic.ContainsKey(injectObjType))
            {
                CachedProperties(injectObjType);
            }

            InjectFields(context, injectObj);
            InjectProperties(context, injectObj);
        }
Exemplo n.º 22
0
        private static void InjectProperties <K>(IContextContainer <K> context, IContextObject injectObj)
        {
            List <PropertyInfo> properties = cachedTypePropertyDic[injectObj.GetType()][ContextUsage.Inject];

            if (properties != null && properties.Count > 0)
            {
                foreach (var property in properties)
                {
                    var attr = property.GetCustomAttribute <ContextIEAttribute>();

                    if (!context.TryGet((K)attr.Key, out object value))
                    {
                        if (value == null && !attr.Optional)
                        {
                            throw new ContextValueNullException(attr.Key);
                        }
                    }
                    property.SetValue(injectObj, value);
                }
            }
        }
Exemplo n.º 23
0
        public static void Extract <K>(IContextContainer <K> context, IContextObject extractObj)
        {
            if (extractObj == null || context == null)
            {
                throw new ArgumentNullException("ContextUtil::Extract->argument is null");
            }

            Type extractObjType = extractObj.GetType();

            if (!cachedTypeFieldDic.ContainsKey(extractObjType))
            {
                CachedFields(extractObjType);
            }

            if (!cachedTypePropertyDic.ContainsKey(extractObjType))
            {
                CachedProperties(extractObjType);
            }

            ExtractFields(context, extractObj);
            ExtractProperties(context, extractObj);
        }
Exemplo n.º 24
0
 public SkillSubContext(NodeMapInfo map, IContextObject owner, IDataScope globalData)
     : base(map, owner, globalData)
 {
 }
Exemplo n.º 25
0
 public static void DoRequest <RequestType>(this IContextObject sender, RequestType request)
     where RequestType : IHas <IRequestLogic <RequestType> >
 {
     sender.DoRequest <RequestType, bool>(request);
 }
Exemplo n.º 26
0
 public static void DoUnregister <RequestType>(this IContextObject sender, Action <RequestType> callBackMethod)
     where RequestType : IHas <IRequestLogic <RequestType, bool> >
 {
     sender.DoUnregister <RequestType, bool>(callBackMethod);
 }
Exemplo n.º 27
0
 internal QueueData(string input, InputResultDelegate callback, IContextObject ctx)
 {
     Input    = input;
     Callback = callback;
     Context  = ctx;
 }
Exemplo n.º 28
0
        private void PipeThreadCallback(string[] inputs, InputResultDelegate callback, IContextObject ctx)
        {
            object output = null;

            for (int i = 0; i < inputs.Length; i++)
            {
                string          input = $"{inputs[i]}".Trim();
                CommandMetadata metadata;
                lock (_lock)
                {
                    //Lock the metadata collection, and grab the first metadata that has a matching executor
                    List <CommandMetadata> metadatas = _metadata.Where(m => m.GetFirstOrDefaultExecutorData(input) != null).ToList();
                    metadata = metadatas.FirstOrDefault();
                }

                if (metadata == null)
                {
                    //No command matches, so ignore this entire piped input
                    callback.Invoke(InputResult.Unhandled, null);
                    break;
                }

                CommandExecutorData exeData = metadata.GetFirstOrDefaultExecutorData(input);

                RegexString trigger = exeData.ExecutorAttribute.CommandMatcher;
                input = trigger.RemoveMatchedString(input);
                object[] arguments = null;
                if (output != null)
                {
                    //If there's output from a previous command, append it to the arguments for this command
                    arguments = new[] { output };
                }

                AbstractParser parser;

                if (i == inputs.Length - 1)
                {
                    //We only want the final parsing to invoke the parser callback
                    parser = _registry.GetParser(_registry, input, arguments, metadata, exeData, ctx, callback);
                }
                else
                {
                    parser = _registry.GetParser(_registry, input, arguments, metadata, exeData, ctx, null);
                }

                //Threads are joined for synchronous behaviour. Running each command concurrently (and thus potentially out of order) will not work here.
                Thread thread = parser.GetThread();
                thread.Start();
                thread.Join();

                //Set output so that it's appended to the end of the next input
                output = parser.Output;
            }
        }
Exemplo n.º 29
0
 public override IContext createContext(NodeMapInfo map, IContextObject owner, IDataScope globalData)
 {
     return(new SkillSubContext(map, owner, globalData));
 }
Exemplo n.º 30
0
        /// <summary>
        /// Creates an array of the given type from the given arguments
        /// </summary>
        /// <param name="type"></param>
        /// <param name="arguments"></param>
        /// <param name="ctx"></param>
        /// <returns></returns>
        public static object CreateArray(Type type, object[] arguments, IContextObject ctx)
        {
            Type             elementType = type.GetElementType();
            IObjectConverter converter   = ctx.Registry.GetConverter(elementType);

            string failedConvert = $"Failed to convert '{string.Join(" ", arguments)}' to Type {type.Name}.";
            string failedCreate  = $"failed to create an instance of type {elementType.Name} from argument ";

            //Create the generic array of the required size
            Array array = (Array)Activator.CreateInstance(type, arguments.Length);

            for (int i = 0; i < array.Length; i++)
            {
                if (converter != null)
                {
                    //if we have a converter, use it
                    object conversion = converter.ConvertFromString(arguments[i].ToString(), ctx);

                    if (conversion == null)
                    {
                        throw new CommandParsingException(
                                  ParserFailReason.ParsingFailed,
                                  failedConvert,
                                  new Exception($"Conversion failed by '{converter.GetType().Name}.'")
                                  );
                    }

                    array.SetValue(conversion, i);
                    continue;
                }

                if (elementType == typeof(string))
                {
                    //strings are special, so have special treatment
                    array.SetValue(arguments[i], i);
                    continue;
                }

                if (elementType.GetTypeInfo().IsValueType)
                {
                    //value types can be created with a typeconverter
                    TypeConverter tc = TypeDescriptor.GetConverter(type.GetElementType());
                    try
                    {
                        //but a bad argument will throw an exception, so handle that
                        array.SetValue(tc.ConvertFrom(arguments[i]), i);
                    }
                    catch (Exception e)
                    {
                        throw new CommandParsingException(ParserFailReason.ParsingFailed, $"TypeConverter {failedCreate} '{arguments[i]}'.", e);
                    }
                }
                else
                {
                    //reference types need to be created with the Activator
                    try
                    {
                        //once again, bad arguments can throw an exception
                        object element = Activator.CreateInstance(elementType, arguments[i]);
                        array.SetValue(element, i);
                    }
                    catch (Exception e)
                    {
                        throw new CommandParsingException(ParserFailReason.ParsingFailed, $"Activator {failedCreate} '{arguments[i]}'.", e);
                    }
                }
            }

            return(array);
        }