Пример #1
0
        /// <summary>
        /// Called to apply this configuration to the passed <paramref name="targets"/> target container.
        /// </summary>
        /// <param name="targets"></param>
        public override void Configure(IRootTargetContainer targets)
        {
            if (targets == null)
            {
                throw new ArgumentNullException(nameof(targets));
            }

            if (!targets.GetOption(EnableAutoFuncInjection.Default))
            {
                return;
            }

            bool enableEnumerables = targets.GetOption(EnableEnumerableInjection.Default);

            targets.TargetRegistered += (object sender, Events.TargetRegisteredEventArgs e) =>
            {
                if (e.Target is AutoFactoryTarget ||
                    (typeof(Delegate).IsAssignableFrom(e.Type) &&
                     e.Type.IsGenericType &&
                     ((e.Type.IsGenericTypeDefinition && FuncTypes.Contains(e.Type)) ||
                      FuncTypes.Contains(e.Type.GetGenericTypeDefinition()))))
                {
                    return;
                }

                IRootTargetContainer root = (IRootTargetContainer)sender;
                var funcType = typeof(Func <>).MakeGenericType(e.Type);
                var existing = root.Fetch(funcType);

                if (existing == null || existing.UseFallback)
                {
                    // you'd think we would bind to the target that was registered, but we don't because
                    // that would prevent auto IEnumerable<delegate_type> from working, and would also prevent
                    // decorators from working.
                    root.Register(new AutoFactoryTarget(funcType, e.Type, Type.EmptyTypes));
                }

                if (enableEnumerables)
                {
                    var enumerableType = typeof(IEnumerable <>).MakeGenericType(e.Type);
                    funcType = typeof(Func <>).MakeGenericType(enumerableType);
                    existing = root.Fetch(funcType);
                    if (existing == null || existing.UseFallback)
                    {
                        root.Register(new AutoFactoryTarget(funcType, enumerableType, Type.EmptyTypes));
                    }
                }
            };
        }
Пример #2
0
        /// <summary>
        /// Adds registrations for <see cref="Collection{T}"/> and <see cref="ReadOnlyCollection{T}"/> to the <paramref name="targets"/> (including
        /// their primary interfaces) so long as none of the types are already registered.
        /// </summary>
        /// <param name="targets"></param>
        public override void Configure(IRootTargetContainer targets)
        {
            if (targets == null)
            {
                throw new ArgumentNullException(nameof(targets));
            }

            if (!targets.GetOption(Options.EnableCollectionInjection.Default))
            {
                return;
            }

            if (targets.Fetch(typeof(Collection <>)) != null ||
                targets.Fetch(typeof(ICollection <>)) != null ||
                targets.Fetch(typeof(ReadOnlyCollection <>)) != null ||
                targets.Fetch(typeof(IReadOnlyCollection <>)) != null)
            {
                return;
            }

            var collectionTarget = Target.ForConstructor(_collectionCtor);

            targets.Register(collectionTarget);
            targets.Register(collectionTarget, typeof(ICollection <>));

            // there's only one constructor for ReadOnlyCollection anyway, so no need to disambiguate
            var roCollectionTarget = Target.ForType(typeof(ReadOnlyCollection <>));

            targets.Register(roCollectionTarget);
            targets.Register(roCollectionTarget, typeof(IReadOnlyCollection <>));
        }
Пример #3
0
 /// <summary>
 /// Gets the compile context for the specified target under test.
 ///
 /// The <see cref="ICompileContext.TargetType"/> is automatically set to the <see cref="ITarget.DeclaredType"/>
 /// of the passed target.
 /// </summary>
 /// <param name="target">The target.</param>
 /// <param name="container">The container to use for the <see cref="ResolveContext"/> from which the compile context
 /// will be created.  If null, then the <see cref="GetDefaultContainer"/> method is called.</param>
 /// <param name="targets">The target container to use for the compile context.  If null, then the <paramref name="container"/>
 /// will be passed to the <see cref="GetDefaultTargetContainer(Container)"/> method (including if one is automatically
 /// built) - with the target container that's returned being used instead.</param>
 protected virtual ICompileContext GetCompileContext(ITarget target, Container container = null, IRootTargetContainer targets = null, Type targetType = null)
 {
     targets   = targets ?? GetDefaultTargetContainer(container);
     container = container ?? GetDefaultContainer(targets);
     // to create a context we resolve the ITargetCompiler from the container.
     // this is usually an internal operation within the container itself.
     return(targets.GetOption <ITargetCompiler>()
            .CreateContext(new ResolveContext(container, targetType ?? target.DeclaredType), targets));
 }
 public EnumerableTargetContainer(IRootTargetContainer root)
     : base(root, typeof(IEnumerable <>))
 {
     this._tracker = root.GetOption <TargetOrderTracker>();
     if (this._tracker == null)
     {
         // this is the first enumerable container in the root
         // so create the tracker and register our own event handler
         // for adding enumerable types.
         root.SetOption(this._tracker = new TargetOrderTracker(Root));
         Root.TargetRegistered       += Root_TargetRegistered;
     }
 }
Пример #5
0
        /// <summary>
        /// Adds the necessary registration to the passed root target container
        /// for <see cref="Lazy{T}"/> so long as no <see cref="ITargetContainer"/> is already
        /// registered.
        /// </summary>
        /// <param name="targets">The root target container to which this configuation will be applied.</param>
        public override void Configure(IRootTargetContainer targets)
        {
            if (targets == null)
            {
                throw new ArgumentNullException(nameof(targets));
            }

            if (!targets.GetOption <EnableAutoLazyInjection>())
            {
                return;
            }

            if (targets.FetchContainer(typeof(Lazy <>)) == null)
            {
                targets.RegisterContainer(typeof(Lazy <>), new AutoLazyTargetContainer(targets));
            }
        }
Пример #6
0
        /// <summary>
        /// Implementation of <see cref="OptionDependentConfigBase.Configure(IRootTargetContainer)"/>
        /// </summary>
        /// <param name="targets"></param>
        /// <remarks>
        /// This implementation registers a special target container (via <see cref="ITargetContainer.RegisterContainer(Type, ITargetContainer)"/>)
        /// for <see cref="IEnumerable{T}"/> in passed <paramref name="targets"/>
        /// if the <see cref="Options.EnableEnumerableInjection"/> option evaluates to <c>true</c> when read from <paramref name="targets"/>.
        ///
        /// This is the default value for that option anyway, so, as the remarks section on the class states, all that's required to enable
        /// the enumerable resolving behaviour is simply to make sure this configuration object is applied to an <see cref="IRootTargetContainer"/></remarks>
        public override void Configure(IRootTargetContainer targets)
        {
            if (targets == null)
            {
                throw new ArgumentNullException(nameof(targets));
            }
            // if an option has already been set on the target container which disables automatic enumerables,
            // then do not apply the configuration.
            if (!targets.GetOption(Options.EnableEnumerableInjection.Default))
            {
                return;
            }

            if (targets.FetchContainer(typeof(IEnumerable <>)) == null)
            {
                targets.RegisterContainer(typeof(IEnumerable <>), new EnumerableTargetContainer(targets));
            }
        }
Пример #7
0
        /// <summary>
        /// Implements the <see cref="OptionDependentConfigBase.Configure(IRootTargetContainer)"/> abstract method
        /// by configuring the passed <paramref name="targets"/> so it can produce targets for any array type, regardless
        /// of whether a single object has been registered for the array's element type.
        ///
        /// After enabling, the ability to register specific targets for concrete array types will still be present.
        /// </summary>
        /// <param name="targets"></param>
        public override void Configure(IRootTargetContainer targets)
        {
            if (targets == null)
            {
                throw new ArgumentNullException(nameof(targets));
            }

            // REVIEW: should this also check that EnableEnumerableInjection is true?
            // At the moment, it's just dependent upon the Enumerable config; but it actually needs it to
            // be *enabled* too.

            if (!targets.GetOption(Options.EnableArrayInjection.Default))
            {
                return;
            }

            targets.RegisterContainer(typeof(Array), new ArrayTargetContainer(targets));
            targets.SetOption <ITargetContainerTypeResolver, Array>(ArrayTypeResolver.Instance);
        }
Пример #8
0
        /// <summary>
        /// Configures the passed <paramref name="targets"/> to enable auto injection of <see cref="List{T}"/>, <see cref="IList{T}"/>
        /// and <see cref="IReadOnlyList{T}"/> by registering a <see cref="Targets.GenericConstructorTarget"/> for
        /// <see cref="List{T}"/> for all three types - so long as none of them already have a registration.
        /// </summary>
        /// <param name="targets"></param>
        public override void Configure(IRootTargetContainer targets)
        {
            if (targets == null)
            {
                throw new ArgumentNullException(nameof(targets));
            }

            if (!targets.GetOption(Options.EnableListInjection.Default))
            {
                return;
            }

            if (targets.Fetch(typeof(List <>)) != null || targets.Fetch(typeof(IList <>)) != null || targets.Fetch(typeof(IReadOnlyList <>)) != null)
            {
                return;
            }

            var target = Target.ForConstructor(_listCtor);

            targets.Register(target);
            targets.Register(target, typeof(IList <>));
            // might be an argument here for a dedication implementation to prevent casting->modification
            targets.Register(target, typeof(IReadOnlyList <>));
        }