/// <summary>
        /// Gets an option either specific to the <paramref name="serviceType"/>, or a global option (if <see cref="Options.EnableGlobalOptions"/> is
        /// enabled), of the type <typeparamref name="TOption"/>
        /// from the <paramref name="targets"/> target container, returning the <paramref name="default"/> if the option has not been explicitly set.
        /// </summary>
        /// <typeparam name="TOption">The type of option to retrieve</typeparam>
        /// <param name="targets">Required. The target container from which the option is to be read.</param>
        /// <param name="serviceType">A type for which the option is to be retrieved.  Note that the default behaviour is to search for
        /// an option which is specific to this service, and then to search for more generally-defined options.  See the remarks section for more.</param>
        /// <param name="default">The default value to return if the option has not been set.</param>
        /// <returns>An option value which was either previously set, or the <paramref name="default"/> if not</returns>
        /// <remarks>Options are frequently used to control how a Rezolver container interprets registrations.  Take, for example, the
        /// <see cref="Options.AllowMultiple"/> option - which is used to control whether a target container accepts multiple registrations
        /// for a given type.
        ///
        /// When defined globally (i.e. without a service type) it determines whether multiple registrations can be performed for all types.  However,
        /// it can also be defined on a per-service basis - so, for example, if you want to restrict an application only to register one target for a
        /// particular service - e.g. <c>IMyApplication</c> - then you can set the <see cref="AllowMultiple"/> option to <c>false</c> specifically against
        /// that type, and multiple registrations will result in a runtime error.
        ///
        /// When searching for service-specific options, generics are automatically processed in descending order of specificity - i.e. <c>IFoo&lt;Bar&gt;</c>
        /// is more specific than <c>IFoo&lt;&gt;</c> - so you can set options for a specific closed generic, or its open generic.
        ///
        /// **Global Fallback**
        ///
        /// In the absence of a service-specific option, a globally-defined option will instead be used if the <see cref="EnableGlobalOptions"/> option
        /// is set to <c>true</c> for the <paramref name="targets"/> target container.  By default, this is enabled.</remarks>
        public static TOption GetOption <TOption>(this ITargetContainer targets, Type serviceType, TOption @default = default)
            where TOption : class
        {
            if (targets == null)
            {
                throw new ArgumentNullException(nameof(targets));
            }

            if (serviceType == null)
            {
                throw new ArgumentNullException(nameof(serviceType));
            }

            bool useGlobalFallback = GetOption(targets, EnableGlobalOptions.Default);

            var optionContainer = (IOptionContainer <TOption>)targets.FetchDirect(typeof(IOptionContainer <,>)
                                                                                  .MakeGenericType(serviceType, typeof(TOption)));

            // currently internal-only option container which allows us to set options
            // that take effect only for generic types (closed/open classes, structs or interfaces)
            if (optionContainer == null && serviceType.IsGenericType)
            {
                optionContainer = targets.FetchDirect <IAnyGenericOptionContainer <TOption> >();
            }

            if (optionContainer == null && useGlobalFallback)
            {
                optionContainer = targets.FetchDirect <IOptionContainer <TOption> >();
            }

            return(optionContainer?.Option ?? @default);
        }
        /// <summary>
        /// Gets a globally-defined option of the type <typeparamref name="TOption"/> from the <paramref name="targets"/> target container,
        /// returning the <paramref name="default"/> if the option has not been explicitly set.
        /// </summary>
        /// <typeparam name="TOption">The type of option to retrieve</typeparam>
        /// <param name="targets">Required. The target container from which the option is to be read.</param>
        /// <param name="default">The default value to return if the option has not been set.</param>
        /// <returns>An option value which was either previously set, or the <paramref name="default"/> if not</returns>
        public static TOption GetOption <TOption>(this ITargetContainer targets, TOption @default = default)
            where TOption : class
        {
            if (targets == null)
            {
                throw new ArgumentNullException(nameof(targets));
            }

            var optionContainer = targets.FetchDirect <IOptionContainer <TOption> >();

            return(optionContainer?.Option ?? @default);
        }
Example #3
0
 internal static TObj FetchDirect <TObj>(this ITargetContainer targets)
 {
     return((TObj)targets.FetchDirect(typeof(TObj)));
 }