/// <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<Bar></c> /// is more specific than <c>IFoo<></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); }
internal static TObj FetchDirect <TObj>(this ITargetContainer targets) { return((TObj)targets.FetchDirect(typeof(TObj))); }