public static ActionInfo GetActionInfo(Type actionType)
        {
            if (actionType == null)
            {
                throw new ArgumentNullException(nameof(actionType));
            }

            lock (_cachedActionInfosLock)
            {
                if (_cachedActionInfos.TryGetValue(actionType, out var actionInfo))
                {
                    return(actionInfo);
                }

                if (!typeof(IAction <T>).IsAssignableFrom(actionType) || actionType.IsAbstract)
                {
                    throw new InvalidOperationException($"Type \"{actionType.FullName}\" does not inherit from \"{typeof(IAction<T>).FullName}\".");
                }

                if (!TryGetActionConstructor(actionType, out var constructorInfo))
                {
                    throw new InvalidOperationException($"No constructor for type \"{actionType.FullName}\" was found.");
                }

                var metadataAttr = actionType.GetCustomAttribute <ActionAttribute>(false);

                var imports = GetTypesToImport(constructorInfo);
                actionInfo = new ActionInfo(
                    actionType,
                    metadataAttr?.FriendlyName,
                    metadataAttr?.Description,
                    imports);

                _cachedActionInfos.Add(actionType, actionInfo);

                return(actionInfo);
            }
        }
 public DefaultActionContext(IExportProvider globalExportProvider, ActionInfo actionInfo)
 {
     _globalExportProvider = globalExportProvider ?? throw new ArgumentNullException(nameof(globalExportProvider));
     _actionInfo           = actionInfo ?? throw new ArgumentNullException(nameof(actionInfo));
 }
예제 #3
0
        /// <summary>
        /// Creates an instance of the action related to the given <see cref="ActionInfo"/>.
        /// Required services and imports will be taken from the given <see cref="IServiceProvider"/> and <see cref="IExportProvider"/>.
        /// </summary>
        /// <param name="actionInfo">The related action-info of the action to create.</param>
        /// <param name="serviceProvider">The service-provider used for dependency-injection.</param>
        /// <param name="exportProvider">The export-provider used for dependency-injection.</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="InvalidOperationException"></exception>
        public static object CreateInstance(ActionInfo actionInfo, IServiceProvider serviceProvider, IExportProvider exportProvider)
        {
            if (actionInfo == null)
            {
                throw new ArgumentNullException(nameof(actionInfo));
            }
            if (serviceProvider == null)
            {
                throw new ArgumentNullException(nameof(serviceProvider));
            }
            if (exportProvider == null)
            {
                throw new ArgumentNullException(nameof(exportProvider));
            }

            var parameters         = actionInfo.Constructor.GetParameters();
            var parameterValues    = new object[parameters.Length];
            var parameterValuesSet = new bool[parameters.Length];

            foreach (var curImport in actionInfo.Imports)
            {
                var importValue = exportProvider.GetExport(curImport.Type, curImport.Name);
                if (importValue == null)
                {
                    throw new InvalidOperationException(
                              string.Format(
                                  "Unable to resolve import for type \"{0}\"{1} while attempting to activate \"{2}\".",
                                  curImport.Type.FullName,
                                  curImport.Name == null ? string.Empty : $" and name \"{curImport.Name}\"",
                                  actionInfo.ActionType.FullName));
                }

                parameterValues[curImport.ConstructorIndex]    = importValue;
                parameterValuesSet[curImport.ConstructorIndex] = true;
            }

            for (int i = 0; i < parameters.Length; i++)
            {
                if (!parameterValuesSet[i])
                {
                    var value = serviceProvider.GetService(parameters[i].ParameterType);
                    if (value == null)
                    {
                        if (!TryGetParameterDefaultValue(parameters[i], out var defaultValue))
                        {
                            throw new InvalidOperationException($"Unable to resolve service for type \"{parameters[i].ParameterType}\" while attempting to activate \"{actionInfo.ActionType.FullName}\".");
                        }

                        parameterValues[i] = defaultValue;
                    }
                    else
                    {
                        parameterValues[i] = value;
                    }
                }
            }

            try
            {
                return(actionInfo.Constructor.Invoke(parameterValues));
            }
            catch (TargetInvocationException ex)
            {
                ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
                // The above line will always throw, but the compiler requires we throw explicitly.
                throw;
            }
        }
예제 #4
0
 public ActionException(string message, Exception innerException, ActionInfo actionInfo)
     : base(message, innerException)
 {
     ActionInfo = actionInfo;
 }
예제 #5
0
 public ActionException(string message, ActionInfo actionInfo)
     : this(message, null, actionInfo)
 {
 }
예제 #6
0
 public ActionCollectionEntry(ActionInfo actionInfo, int priority)
 {
     ActionInfo = actionInfo ?? throw new ArgumentNullException(nameof(actionInfo));
     Priority   = priority;
 }