예제 #1
0
        /// <summary>
        /// Executes a given constructor (identified by <paramref name="constructorSelector"/>) by reading values out of the picker
        /// (or prompting the user if <paramref name="pickerArgsIfAny"/> is null)
        /// </summary>
        /// <param name="toConstruct">The Type you want to construct</param>
        /// <param name="constructorSelector">Selects which constructor on <paramref name="toConstruct"/> you want to invoke</param>
        /// <param name="pickerArgsIfAny"></param>
        /// <returns></returns>
        protected object Construct(Type toConstruct, Func <ObjectConstructor, ConstructorInfo> constructorSelector,
                                   IEnumerable <CommandLineObjectPickerArgumentValue> pickerArgsIfAny = null)
        {
            var objectConstructor = new ObjectConstructor();

            var invoker = new CommandInvoker(BasicActivator);

            var constructor = constructorSelector(objectConstructor);

            List <object> constructorValues = new List <object>();

            var pickerEnumerator = pickerArgsIfAny?.GetEnumerator();

            foreach (var parameterInfo in constructor.GetParameters())
            {
                var required          = new RequiredArgument(parameterInfo);
                var parameterDelegate = invoker.GetDelegate(required);

                if (parameterDelegate.IsAuto)
                {
                    constructorValues.Add(parameterDelegate.Run(required));
                }
                else
                {
                    //it's not auto
                    if (pickerEnumerator != null)
                    {
                        pickerEnumerator.MoveNext();

                        if (pickerEnumerator.Current == null)
                        {
                            throw new ArgumentException($"Value needed for parameter '{required.Name}' (of type '{required.Type}')");
                        }

                        //construct with the picker arguments
                        if (!pickerEnumerator.Current.HasValueOfType(required.Type))
                        {
                            throw new NotSupportedException($"Argument '{pickerEnumerator.Current.RawValue}' could not be converted to required Type '{required.Type}' for argument {required.Name}");
                        }

                        //it is a valid object yay!
                        constructorValues.Add(pickerEnumerator.Current.GetValueForParameterOfType(required.Type));
                    }
                    else
                    {
                        //construct by prompting user for the values
                        constructorValues.Add(invoker.GetValueForParameterOfType(parameterInfo));
                    }
                }
            }

            pickerEnumerator?.Dispose();

            return(constructor.Invoke(constructorValues.ToArray()));
        }
예제 #2
0
        public CommandInvokerDelegate GetDelegate(RequiredArgument required)
        {
            var match = _argumentDelegates.FirstOrDefault(k => k.CanHandle(required.Type));

            if (match != null)
            {
                return(match);
            }

            if (required.HasDefaultValue && required.DefaultValue != null)
            {
                return(new CommandInvokerFixedValueDelegate(required.DefaultValue));
            }

            return(null);
        }
예제 #3
0
 private object GetValueFor(RequiredArgument a)
 {
     return(GetDelegate(a)?.Run(a));
 }
예제 #4
0
 private T SelectOne <T>(RequiredArgument parameterInfo)
 {
     return((T)_basicActivator.SelectOne(parameterInfo.Name, _basicActivator.GetAll <T>().Cast <IMapsDirectlyToDatabaseTable>().ToArray()));
 }
예제 #5
0
        private void ExecuteCommand(ConstructorInfo constructorInfo, CommandLineObjectPicker picker)
        {
            List <object> parameterValues = new List <object>();
            bool          complainAboutExtraParameters = true;

            int idx = 0;

            //for each parameter on the constructor we want to invoke
            foreach (var parameterInfo in constructorInfo.GetParameters())
            {
                var required = new RequiredArgument(parameterInfo);

                var argDelegate = GetDelegate(required);

                //if it is an easy one to automatically fill e.g. IBasicActivateItems
                if (argDelegate != null && argDelegate.IsAuto)
                {
                    parameterValues.Add(argDelegate.Run(required));
                }
                else
                //if the constructor argument is a picker, use the one passed in
                if (parameterInfo.ParameterType == typeof(CommandLineObjectPicker))
                {
                    if (picker == null)
                    {
                        throw new ArgumentException($"Type {constructorInfo.DeclaringType} contained a constructor which took an {parameterInfo.ParameterType} but no picker was passed");
                    }

                    parameterValues.Add(picker);

                    //the parameters are expected to be consumed by the target constructors so it's not really a problem if there are extra
                    complainAboutExtraParameters = false;
                    continue;
                }
                else
                //if we have argument values specified
                if (picker != null)
                {
                    //and the specified value matches the expected parameter type
                    if (picker.HasArgumentOfType(idx, parameterInfo.ParameterType))
                    {
                        //consume a value
                        parameterValues.Add(picker[idx].GetValueForParameterOfType(parameterInfo.ParameterType));
                        idx++;
                        continue;
                    }

                    throw new Exception($"Expected parameter at index {idx} to be a {parameterInfo.ParameterType} (for parameter '{parameterInfo.Name}') but it was {(idx >= picker.Length ? "Missing":picker[idx].RawValue)}");
                }
                else
                {
                    parameterValues.Add(GetValueForParameterOfType(parameterInfo));
                }
            }

            if (picker != null && idx < picker.Length && complainAboutExtraParameters)
            {
                throw new Exception("Unrecognised extra parameter " + picker[idx].RawValue);
            }

            var instance = (IAtomicCommand)constructorInfo.Invoke(parameterValues.ToArray());

            if (instance.IsImpossible)
            {
                CommandImpossible?.Invoke(this, new CommandEventArgs(instance));
                return;
            }

            instance.Execute();
            CommandCompleted?.Invoke(this, new CommandEventArgs(instance));
        }
예제 #6
0
 private T[] SelectMany <T>(RequiredArgument parameterInfo)
 {
     return
         (_basicActivator.SelectMany(parameterInfo.Name, typeof(T), _basicActivator.GetAll <T>().Cast <IMapsDirectlyToDatabaseTable>().ToArray())
          .Cast <T>().ToArray());
 }
예제 #7
0
 public object GetValueForParameterOfType(RequiredArgument a)
 {
     return(GetDelegate(a)?.Run(a));
 }
예제 #8
0
 private string GetPromptFor(RequiredArgument p)
 {
     return($"Value needed for {p.Name} ({p.Type.Name})");
 }
예제 #9
0
 private IPipeline SelectPipeline(RequiredArgument arg)
 {
     return((IPipeline)_basicActivator.SelectOne(GetPromptFor(arg), _basicActivator.RepositoryLocator.CatalogueRepository.GetAllObjects <Pipeline>().ToArray()));
 }