Exemplo n.º 1
0
 private static void RegisterAutoFactoryInternal(IRootTargetContainer targets, Type delegateType, Type returnType, Type[] parameterTypes)
 {
     // create an unbound AutoFactoryTarget and register it.
     // this will also trigger a projection to be registered from IEnumerable<ReturnType> to IEnumerable<DelegateType>
     // since the newly created & registered target is unbound.
     targets.Register(new AutoFactoryTarget(delegateType, returnType, parameterTypes));
 }
Exemplo n.º 2
0
 /// <summary>
 /// Applies each configuration in this collection to the passed <paramref name="targets"/> <see cref="ITargetContainer"/>.
 /// </summary>
 /// <param name="targets">The target container to which the configurations in this collection are to be applied.</param>
 /// <remarks>The implementation runs through each configuration that has been added to the collection, in dependency
 /// order, calling its <see cref="ITargetContainerConfig.Configure(IRootTargetContainer)"/> method.</remarks>
 public void Configure(IRootTargetContainer targets)
 {
     foreach (var config in Ordered)
     {
         config.Configure(targets);
     }
 }
Exemplo n.º 3
0
 /// <summary>
 /// Applies the behaviours in this collection to the passed <paramref name="container"/> and
 /// <paramref name="targets"/>.
 /// </summary>
 /// <param name="container">The container to which the behaviours are being attached.</param>
 /// <param name="targets">The target container used by the <paramref name="container"/> for its registrations.</param>
 /// <remarks>The implementation runs through each behaviour that has been added to the collection, in dependency
 /// order, calling its <see cref="IContainerConfig.Configure(Container, IRootTargetContainer)"/> method.</remarks>
 public void Configure(Container container, IRootTargetContainer targets)
 {
     foreach (var behaviour in Ordered)
     {
         behaviour.Configure(container, targets);
     }
 }
 /// <summary>
 /// Non-generic version of <see cref="RegisterProjection{TFrom, TTo}(IRootTargetContainer, Func{IRootTargetContainer, ITarget, ITarget})"/>
 /// </summary>
 /// <param name="targets"></param>
 /// <param name="fromType">The type of the enumerable that provides the source of the projection</param>
 /// <param name="toType">The type of the enumerable that will be the output of the projection</param>
 /// <param name="implementationTargetFactory">A factory callback that will be called once for each target in the
 /// input enumerable - the target returned by the factory will then be used to produce the projected element
 /// in the output enumerable.</param>
 public static void RegisterProjection(this IRootTargetContainer targets, Type fromType, Type toType, Func <IRootTargetContainer, ITarget, ITarget> implementationTargetFactory)
 {
     RegisterProjectionInternal(targets ?? throw new ArgumentNullException(nameof(targets)),
                                fromType ?? throw new ArgumentNullException(nameof(fromType)),
                                toType ?? throw new ArgumentNullException(nameof(toType)),
                                implementationTargetFactory ?? throw new ArgumentNullException(nameof(implementationTargetFactory)));
 }
Exemplo n.º 5
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 <>));
        }
Exemplo n.º 6
0
        /// <summary>
        /// Implements the <see cref="IContainerConfig.Configure(Container, IRootTargetContainer)"/> method,
        /// registering all the targets necessary to use expression-based compilation for all the standard targets
        /// defined in the <c>Rezolver</c> core library.
        /// </summary>
        /// <param name="container">The container - ignored.</param>
        /// <param name="targets">Required - the target container into which the various targets will be registered.</param>
        /// <remarks>All targets registered by this function are <see cref="ObjectTarget"/> targets backed by concrete instances
        /// of the various components (compiler etc).</remarks>
        public virtual void Configure(Container container, IRootTargetContainer targets)
        {
            if (targets == null)
            {
                throw new ArgumentNullException(nameof(targets));
            }
            // note - the singleton container is done like this because the expression compiler which uses
            // it Resolves it from the container during compilation.  This is to ensure that each container
            // gets the same singleton container (including OverridingContainer), rather than a single shared one
            // from the target container option.
            targets.RegisterObject(new SingletonTarget.SingletonContainer());
            // targets.RegisterObject(new ExpressionBuilderCache(container));
            // will be how containers pick up and use this compiler
            targets.SetOption <ITargetCompiler>(ExpressionCompiler.Default);
            // if you're looking to re-enter the compilation process for a particular
            // target - then you should request our compiler via the type IExpressionCompiler
            targets.SetOption <IExpressionCompiler>(ExpressionCompiler.Default);

            // loop through all the types in the core Rezolver assembly's Rezolver.Targets namespace, searching for an implementing
            // type in this assembly
            foreach (var registration in GetStandardTargetBuilders())
            {
                targets.SetOption(registration.Instance, registration.TargetType);
            }
        }
Exemplo n.º 7
0
 /// <summary>
 /// Constructs a new instance of the <see cref="ScopedContainer"/> class.
 /// </summary>
 /// <param name="targets">Optional.  Contains the targets that will be used as the source of registrations for the
 /// container, ultimately being passed to the <see cref="Targets"/> property.
 ///
 /// If not provided, then a new <see cref="TargetContainer"/> will be created.</param>
 /// <param name="config">Can be null.  A configuration to apply to this container (and, potentially its
 /// <see cref="Targets"/>).  If not provided, then the <see cref="Container.DefaultConfig"/> will be used</param>
 public ScopedContainer(IRootTargetContainer targets = null, IContainerConfig config = null)
     : base(targets)
 {
     // annoying: double assignment here (base already initialises it...)
     _scope = new DisposingContainerScope(this);
     (config ?? DefaultConfig).Configure(this, Targets);
 }
Exemplo n.º 8
0
 internal static IEnumerable <ITarget> FetchAllCompatibleTargetsInternal(this IRootTargetContainer rootContainer, Type serviceType)
 {
     return(rootContainer.FetchAll(serviceType)
            .Concat(rootContainer.GetKnownCompatibleTypes(serviceType)
                    .SelectMany(compatibleType => rootContainer.FetchAll(compatibleType)
                                .Select(t => VariantMatchTarget.Wrap(t, serviceType, compatibleType))
                                )).Distinct(TargetIdentityComparer.Instance));
 }
        /// <summary>
        /// Non-generic version of <see cref="RegisterProjection{TFrom, TTo, TImplementation}(IRootTargetContainer)"/>
        /// </summary>
        /// <param name="targets"></param>
        /// <param name="fromType">The type of the enumerable that provides the source of the projection.</param>
        /// <param name="toType">The type of the enumerable produced by the projection.</param>
        /// <param name="implementationType">The type to be created for each element in the output enumerable.  Must be able to
        /// be created via automatic constructor injection.</param>
        public static void RegisterProjection(this IRootTargetContainer targets, Type fromType, Type toType, Type implementationType)
        {
            if (implementationType == null)
            {
                throw new ArgumentNullException(nameof(implementationType));
            }

            RegisterProjection(targets, fromType, toType, (r, t) => implementationType);
        }
        /// <summary>
        /// Attaches this behaviour to the target container, adding a registration to the <paramref name="targets"/>
        /// for the type <see cref="ResolveContext"/>.
        ///
        /// Note - if the <paramref name="targets"/> already has a registration for <see cref="ResolveContext"/>,
        /// then the behaviour DOES NOT overwrite it.
        /// </summary>
        /// <param name="targets"></param>
        public void Configure(IRootTargetContainer targets)
        {
            var existing = targets.Fetch(typeof(ResolveContext));

            if (existing == null || existing.UseFallback)
            {
                targets.Register(this._target);
            }
        }
 internal ProjectionTargetContainer(
     IRootTargetContainer root,
     Type sourceElementType,
     Type outputElementType,
     Func <IRootTargetContainer, ITarget, TargetProjection> targetProjectionFactory)
     : this(root, sourceElementType, outputElementType)
 {
     TargetProjectionFactory = targetProjectionFactory ?? throw new ArgumentNullException(nameof(targetProjectionFactory));
 }
Exemplo n.º 12
0
        // when registering an unbound target, we also automatically register
        // a projection for the delegate type which is fed by an enumerable of the return
        // type of the delegate.  So IEnumerable<Func<Foo>> <== IEnumerable<Foo>
        void INotifyRegistrationTarget.OnRegistration(IRootTargetContainer root, Type registeredType)
        {
            if (this.BoundTarget == null)
            {
                root.RegisterProjection(ReturnType, registeredType, CreateTarget);
            }

            AutoFactoryTarget CreateTarget(IRootTargetContainer root2, ITarget source) => new AutoFactoryTarget(registeredType, ReturnType, ParameterTypes, source);
        }
        private ProjectionTargetContainer(IRootTargetContainer root, Type sourceElementType, Type outputElementType)
        {
            Root = root;
            SourceElementType    = sourceElementType;
            OutputElementType    = outputElementType;
            SourceEnumerableType = typeof(IEnumerable <>).MakeGenericType(sourceElementType);
            OutputEnumerableType = typeof(IEnumerable <>).MakeGenericType(outputElementType);

            Root.AddKnownType(OutputEnumerableType);
        }
        /// <summary>
        /// Create a new instance of the <see cref="DecoratingTargetContainer"/> class to decorate
        /// instances of <paramref name="decoratedType"/> with instances produced by the <paramref name="decoratorTarget"/>.
        /// </summary>
        /// <param name="root">Required.  The root <see cref="ITargetContainer"/> to which this decorating
        /// container will be registered.</param>
        /// <param name="decoratorTarget"></param>
        /// <param name="decoratedType"></param>
        public DecoratingTargetContainer(IRootTargetContainer root, ITarget decoratorTarget, Type decoratedType)
            : this(root, decoratedType)
        {
            if (decoratorTarget == null)
            {
                throw new ArgumentNullException(nameof(decoratorTarget));
            }

            DecoratorFactory = (ta, ty) => decoratorTarget;
        }
 /// <summary>
 /// Calls <see cref="IRootTargetContainer.GetContainerRegistrationType(Type)"/> to get the correct registration type for the target container
 /// that should own a target that will be registered against the given <paramref name="serviceType"/>.  Once obtained, that type is then
 /// passed to the <see cref="IRootTargetContainer.CreateTargetContainer(Type)"/> to create the correct <see cref="ITargetContainer"/> for
 /// that container registration type.
 ///
 /// This is typically used by 'advanced' target containers which wrap others under potentially any type and which therefore need to reuse
 /// the root container's logic for ensuring that registrations are handled correctly.
 /// </summary>
 /// <param name="rootContainer"></param>
 /// <param name="serviceType"></param>
 /// <returns></returns>
 public static ITargetContainer CreateTargetContainerForServiceType(this IRootTargetContainer rootContainer, Type serviceType)
 {
     if (rootContainer == null)
     {
         throw new ArgumentNullException(nameof(rootContainer));
     }
     return(CreateTargetContainerForServiceTypeInternal(
                rootContainer,
                serviceType ?? throw new ArgumentNullException(nameof(serviceType))));
 }
Exemplo n.º 16
0
        /// <summary>
        /// Constructs a new instance of the <see cref="Container"/> class.
        /// </summary>
        /// <param name="targets">Optional.  The target container whose registrations will be used for dependency lookup
        /// when <see cref="Resolve(ResolveContext)"/> (and other operations) is called.  If not provided, a new
        /// <see cref="TargetContainer"/> instance is constructed.  This will ultimately be available to inherited types,
        /// after construction, through the <see cref="Targets"/> property.</param>
        protected Container(IRootTargetContainer targets = null)
        {
            _scope  = new NonTrackingContainerScope(this);
            Targets = targets ?? new TargetContainer();
#if !ENABLE_IL_EMIT
            _cache = new ConcurrentCache(GetWorker);
#else
            _dynCache = DynamicCache.CreateCache(this);
#endif
        }
Exemplo n.º 17
0
        /// <summary>
        /// Constructs a new instance of the <see cref="Container"/> class.
        /// </summary>
        /// <param name="targets">Optional.  The target container whose registrations will be used for dependency lookup when
        /// <see cref="Resolve(ResolveContext)"/> (and other operations) is called.  If not provided, a new
        /// <see cref="TargetContainer"/> instance is constructed.  This will ultimately be available
        /// to derived types, after construction, through the <see cref="Targets"/> property.</param>
        /// <param name="config">Can be null.  Configuration to apply to this container (and, potentially its <see cref="Targets"/>).
        /// If not provided, then the <see cref="DefaultConfig"/> will be used.</param>
        /// <remarks>Note to inheritors - this constructor throws an <see cref="InvalidOperationException"/> if used by a derived class,
        /// because the application of configuration to the container will likely cause virtual methods to be called.  Instead, you
        /// should declare your own constructor with the same signature which chains instead to the <see cref="Container.Container(IRootTargetContainer)"/>
        /// protected constructor; and then you should apply the configuration yourself in that constructor (falling back to
        /// <see cref="DefaultConfig"/> if null).</remarks>
        public Container(IRootTargetContainer targets = null, IContainerConfig config = null)
            : this(targets)
        {
            if (GetType() != typeof(Container))
            {
                throw new InvalidOperationException("This constructor must not be used by derived types because applying configuration will most likely trigger calls to virtual methods on this instance.  Please use the protected constructor and apply configuration explicitly in your derived class");
            }

            _scope = new NonTrackingContainerScope(this);
            (config ?? DefaultConfig).Configure(this, Targets);
        }
Exemplo n.º 18
0
        /// <summary>
        /// Initializes a new instance of the <see cref="GenericTargetContainer"/> class.
        /// </summary>
        /// <param name="root">Required.  The root <see cref="ITargetContainer"/> in which the new generic target container
        /// will be registered.</param>
        /// <param name="genericType">Required. The generic type definition that all targets and subcontainers registered
        /// to the new container will have in common.</param>
        public GenericTargetContainer(IRootTargetContainer root, Type genericType)
            : base(root ?? throw new ArgumentNullException(nameof(root)))
        {
            GenericType = genericType ?? throw new ArgumentNullException(nameof(genericType));
            if (!GenericType.IsGenericTypeDefinition)
            {
                throw new ArgumentException("type must be a generic type definition", nameof(genericType));
            }

            Targets = new TargetListContainer(Root, genericType);
        }
 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;
     }
 }
        private static void RegisterProjectionInternal(this IRootTargetContainer targets, Type fromType, Type toType, Func <IRootTargetContainer, ITarget, ITarget> implementationTargetFactory)
        {
            RegisterProjectionInternal(targets, fromType, toType, (r, t) =>
            {
                var target = implementationTargetFactory(r, t);
                if (target == null)
                {
                    throw new InvalidOperationException("Implementation target factory returned a null target");
                }

                return(new TargetProjection(target, target.DeclaredType));
            });
        }
Exemplo n.º 21
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));
                    }
                }
            };
        }
Exemplo n.º 22
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));
            }
        }
Exemplo n.º 23
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));
            }
        }
Exemplo n.º 24
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);
        }
        /// <summary>
        /// Non-generic version of <see cref="RegisterProjection{TFrom, TTo}(IRootTargetContainer, Func{IRootTargetContainer, ITarget, Type})"/>
        /// </summary>
        /// <param name="targets"></param>
        /// <param name="fromType">The type of the enumerable that provides the source of the projection.</param>
        /// <param name="toType">The type of the enumerable produced by the projection.</param>
        /// <param name="implementationTypeSelector">A callback to be invoked for each target in the input enumerable which
        /// provides the type that is to be created for the corresponding element in the output enumerable.</param>
        public static void RegisterProjection(this IRootTargetContainer targets, Type fromType, Type toType, Func <IRootTargetContainer, ITarget, Type> implementationTypeSelector)
        {
            if (targets == null)
            {
                throw new ArgumentNullException(nameof(targets));
            }

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

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

            if (fromType == toType)
            {
                throw new ArgumentException($"The output enumerable type ({toType}) cannot be the same as the input enumerable type ({fromType})", nameof(toType));
            }

            if (implementationTypeSelector == null)
            {
                implementationTypeSelector = (r, t) => toType;
            }

            RegisterProjectionInternal(targets, fromType, toType, (r, t) =>
            {
                var implementationType = implementationTypeSelector(r, t);
                if (implementationType == null)
                {
                    throw new InvalidOperationException($"Implementation type returned for projection from {fromType} to {toType} for target {t} returned null");
                }

                // REVIEW: Cache the .ForType result on a per-type basis? It's container-agnostic.
                var target = r.Fetch(implementationType);
                return(new TargetProjection(target != null && !target.UseFallback ? target : Target.ForType(implementationType), implementationType));
            });
        }
Exemplo n.º 26
0
        /// <summary>
        /// Registers an <see cref="AutoFactoryTarget"/> for the given delegate type <typeparamref name="TDelegate"/>, enabling
        /// the container to automatically build and inject a delegate which uses the container to produce a result.
        ///
        /// This method and its overload can be used for any delegate type.
        /// </summary>
        /// <typeparam name="TDelegate">The type of delegate to be injected. Must have a non-void return type
        /// and all its parameters must be of distinct types.</typeparam>
        /// <param name="targets">Required. The target container in which the registration is to be made.</param>
        public static void RegisterAutoFactory <TDelegate>(this IRootTargetContainer targets)
            where TDelegate : Delegate
        {
            if (targets == null)
            {
                throw new ArgumentNullException(nameof(targets));
            }

            var(returnType, parameterTypes) = TypeHelpers.DecomposeDelegateType(typeof(TDelegate));

            if (!IsValidReturnType(returnType))
            {
                throw new ArgumentException($"Type argument {typeof(TDelegate)} for {nameof(TDelegate)} is invalid - must be a delegate with a non-void return type.", nameof(TDelegate));
            }

            if (!AreValidParameterTypes(parameterTypes))
            {
                throw new ArgumentException($"The parameter types for {typeof(TDelegate)} are invalid - they must all be unique", nameof(TDelegate));
            }

            RegisterAutoFactoryInternal(targets, typeof(TDelegate), returnType, parameterTypes);
        }
Exemplo n.º 27
0
        /// <summary>
        /// Registers an <see cref="AutoFactoryTarget"/> for the given <paramref name="delegateType"/>, enabling
        /// the container to automatically build and inject a delegate which uses the container to produce a result.
        ///
        /// This method and its overload can be used for any delegate type.
        /// </summary>
        /// <param name="targets">Required. The target container in which the registration is to be made.</param>
        /// <param name="delegateType">Required. Must have a non-void return type and all its parameters must be of distinct types.</param>
        public static void RegisterAutoFactory(this IRootTargetContainer targets, Type delegateType)
        {
            if (targets == null)
            {
                throw new ArgumentNullException(nameof(targets));
            }

            // assume the type is a valid delegate type
            var(returnType, parameterTypes) = TypeHelpers.DecomposeDelegateType(delegateType);

            if (!IsValidReturnType(returnType))
            {
                throw new ArgumentException($"{delegateType} is invalid - must be a delegate with a non-void return value", nameof(delegateType));
            }

            if (!AreValidParameterTypes(parameterTypes))
            {
                throw new ArgumentException($"The parameter types for {delegateType} are invalid - they must all be unique, non ref/out types", nameof(delegateType));
            }

            RegisterAutoFactoryInternal(targets, delegateType, returnType, parameterTypes);
        }
Exemplo n.º 28
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 <>));
        }
Exemplo n.º 29
0
 /// <summary>
 /// Creates a new instance of the <see cref="TargetTypeSelector"/> type for the given
 /// <paramref name="type"/>.
 /// </summary>
 /// <param name="type">The type for which a list of search types is to be produced.</param>
 /// <param name="rootTargets">The root target container</param>
 public TargetTypeSelector(Type type, IRootTargetContainer rootTargets = null)
 {
     Type        = type;
     RootTargets = rootTargets;
     _results    = Run(new TargetTypeSelectorParams(Type, this)).Distinct().ToArray();
 }
 private DecoratingTargetContainer(IRootTargetContainer root, Type decoratedType)
 {
     Root          = root ?? throw new ArgumentNullException(nameof(root));
     DecoratedType = decoratedType ?? throw new ArgumentNullException(nameof(decoratedType));
 }