예제 #1
0
파일: Container.cs 프로젝트: csf-dev/FlexDi
        /// <summary>
        /// Initializes a new instance of the <see cref="T:CSF.FlexDi.Container"/> class.
        /// </summary>
        /// <remarks>
        /// <para>
        /// All of the parameters to this method are optional.  Any which are not provided will be fulfilled using
        /// default implementations.
        /// </para>
        /// <para>
        /// Of the parameters which might be used, the most useful is likely to be <paramref name="options"/> and
        /// <paramref name="parentContainer"/>.
        /// </para>
        /// </remarks>
        /// <param name="registry">An optional service registry instance.</param>
        /// <param name="cache">An optional service cache instance.</param>
        /// <param name="resolver">An optional resolver instance.</param>
        /// <param name="disposer">An optional service disposer instance.</param>
        /// <param name="options">A set of container options.</param>
        /// <param name="parentContainer">An optional parent container - indicating that this container is the child of another.</param>
        /// <param name="resolverFactory">An optional resolver factory instance.</param>
        public Container(IRegistersServices registry           = null,
                         ICachesResolvedServiceInstances cache = null,
                         IFulfilsResolutionRequests resolver   = null,
                         IDisposesOfResolvedInstances disposer = null,
                         ContainerOptions options          = null,
                         IContainer parentContainer        = null,
                         ICreatesResolvers resolverFactory = null)
        {
            disposedValue = false;

            this.parentContainer = parentContainer;

            this.options        = GetContainerOptions(options, parentContainer);
            constructorSelector = new ConstructorWithMostParametersSelector(this.options.UseNonPublicConstructors);

            this.registry      = registry ?? new Registry();
            this.cache         = cache ?? new ResolvedServiceCache();
            this.disposer      = disposer ?? new ServiceInstanceDisposer();
            this.registryStack = new RegistryStackFactory().CreateRegistryStack(this);
            this.resolver      = resolver ?? GetResolver(resolverFactory);

            this.resolver.ServiceResolved += InvokeServiceResolved;

            PerformSelfRegistrations();
        }
예제 #2
0
 /// <summary>
 /// Sets the given <paramref name="parent"/> as this instance's
 /// <see cref="IServiceRegistrationProvider.ParentServiceProvider"/>.
 /// Requests for types HERE will
 /// first check this container itself; and if not registered
 /// here, they will then check this parent. Additionally,
 /// dependencies needed for services constructed HERE will first
 /// check this container, and if not resolved here, WILL check
 /// this <paramref name="parent"/>. Note that dependencies needed
 /// for Types registered on the <paramref name="parent"/> will NOT
 /// come from this or any other child containers --- and at the same
 /// time, ALL parents WILL be checked up the hierarchy.
 /// NOTICE that this means that the <paramref name="parent"/>
 /// container MUST live at least as long as THIS container,
 /// AND all parents up the hierarchy must also --- otherwise dependencies
 /// resolved from a parent container could be disposed before
 /// a service that is using them.
 /// </summary>
 /// <param name="parent">Not null.</param>
 /// <exception cref="ArgumentNullException"></exception>
 /// <exception cref="ArgumentException">The <paramref name="parent"/>
 /// cannot be cyclically scoped, AND THIS
 /// <see cref="IServiceRegistrationProvider.ParentServiceProvider"/>
 /// must be null at this time.</exception>
 internal void Scope(IServiceProvider parent)
 {
     if (parent == null)
     {
         throw new ArgumentNullException(nameof(parent));
     }
     if (object.ReferenceEquals(this, parent))
     {
         throw new ArgumentException($"Requested parent container is THIS: {parent}", nameof(parent));
     }
     lock (registrations) {
         if (parentServiceProvider != null)
         {
             throw new ArgumentException($"Container cannot be scoped twice: {this}", nameof(parent));
         }
         IServiceProvider checkParent = (parent as IServiceRegistrationProvider)?.ParentServiceProvider;
         while (checkParent != null)
         {
             if (object.ReferenceEquals(checkParent, parent) ||
                 object.ReferenceEquals(checkParent, this))
             {
                 throw new ArgumentException($"Container cannot be scoped twice: {parent}", nameof(parent));
             }
             checkParent = (checkParent as IServiceRegistrationProvider)?.ParentServiceProvider;
         }
         parentServiceProvider             = parent;
         parentServiceRegistrationProvider = parent as IServiceRegistrationProvider;
     }
 }
예제 #3
0
        public void Resolve_using_request_can_get_registered_service_without_name(IServiceRegistrationProvider provider,
                                                                                  [Registration] IServiceRegistration registration,
                                                                                  ResolutionRequest request)
        {
            // Arrange
            var sut      = GetSut(provider);
            var instance = new SampleServiceImplementationOne();

            Mock.Get(provider)
            .Setup(x => x.CanFulfilRequest(request))
            .Returns(false);
            Mock.Get(provider)
            .Setup(x => x.Get(request))
            .Returns((IServiceRegistration)null);
            Mock.Get(provider)
            .Setup(x => x.CanFulfilRequest(It.Is <ResolutionRequest>(r => r.ServiceType == request.ServiceType && r.Name == null)))
            .Returns(true);
            Mock.Get(provider)
            .Setup(x => x.Get(It.Is <ResolutionRequest>(r => r.ServiceType == request.ServiceType && r.Name == null)))
            .Returns(registration);
            Mock.Get(registration)
            .Setup(x => x.GetFactoryAdapter(request))
            .Returns(new InstanceFactory(instance));

            // Act
            var result = sut.Resolve(request);

            // Assert
            Assert.That(result.ResolvedObject, Is.SameAs(instance));
        }
예제 #4
0
        public static bool TryInject(
            IServiceRegistrationProvider serviceProvider,
            object target,
            Type attributeType,
            ITrace logger = null,
            Func <Type, object> instanceProvider = null,
            bool tryConstructArguments           = false,
            bool?requireConstructorAttributes    = null,
            IReadOnlyCollection <Type> constructorAttributeTypes = null)
        {
            if (serviceProvider == null)
            {
                throw new ArgumentNullException(nameof(serviceProvider));
            }
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }
            if (attributeType == null)
            {
                throw new ArgumentNullException(nameof(attributeType));
            }
            if ((constructorAttributeTypes == null) ||
                (constructorAttributeTypes.Count == 0))
            {
                constructorAttributeTypes = new[] { typeof(ServiceProviderConstructorAttribute) }
            }
            ;
            ServiceConstructorRequest request
                = new ServiceConstructorRequest(logger ?? TraceSources.For(typeof(ServiceConstructorMethods)));

            request.Logger.Verbose(
                "Injecting '{0}' on '{1}'.",
                attributeType.GetFriendlyFullName(),
                target.GetType().GetFriendlyFullName());
            if (ServiceConstructorMethods.invokeMember(
                    ServiceConstructorMethods.findMethods(target, attributeType, request.TraceStack),
                    true,
                    target,
                    out _,
                    request,
                    serviceProvider,
                    instanceProvider,
                    tryConstructArguments,
                    requireConstructorAttributes,
                    constructorAttributeTypes,
                    false))
            {
                request.Logger.Verbose(
                    "Inject result for '{0}' on '{1}' is true.",
                    attributeType.GetFriendlyFullName(),
                    target.GetType().GetFriendlyFullName());
                return(true);
            }
            request.Logger.Info(
                "Inject result for '{0}' on '{1}' is false.",
                attributeType.GetFriendlyFullName(),
                target.GetType().GetFriendlyFullName());
            return(false);
        }
예제 #5
0
        /// <summary>
        /// Constructor. NOTICE that the <paramref name="serviceProvider"/>
        /// MUST NOT implement <see cref="IServiceRegistrationProvider"/>.
        /// </summary>
        /// <param name="serviceProvider">Required; and MUST NOT implement
        /// <see cref="IServiceRegistrationProvider"/>.</param>
        /// <param name="parentServiceProvider">Optional parent for the
        /// <see cref="IServiceRegistrationProvider.ParentServiceProvider"/>.</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        public ServiceRegistrationProviderWrapper(
            IServiceProvider serviceProvider,
            IServiceProvider parentServiceProvider = null)
        {
            if (serviceProvider is IServiceRegistrationProvider)
            {
                throw new ArgumentException(
                          $"{nameof(ServiceRegistrationProviderWrapper)} {nameof(serviceProvider)}"
                          + $" must not implement {nameof(IServiceRegistrationProvider)}"
                          + $": '{serviceProvider.GetType().GetFriendlyFullName()}'.");
            }
            this.serviceProvider              = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
            ParentServiceProvider             = parentServiceProvider;
            parentServiceRegistrationProvider = parentServiceProvider as IServiceRegistrationProvider;
            if (object.ReferenceEquals(serviceProvider, parentServiceProvider))
            {
                throw new ArgumentException(
                          $"Requested parent container is THIS: {parentServiceProvider}",
                          nameof(parentServiceProvider));
            }
            IServiceProvider checkParent = parentServiceRegistrationProvider?.ParentServiceProvider;

            while (checkParent != null)
            {
                if (object.ReferenceEquals(checkParent, parentServiceProvider) ||
                    object.ReferenceEquals(checkParent, serviceProvider))
                {
                    throw new ArgumentException(
                              $"Container cannot be scoped twice: {parentServiceProvider}",
                              nameof(parentServiceProvider));
                }
                checkParent = (checkParent as IServiceRegistrationProvider)?.ParentServiceProvider;
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="T:CSF.FlexDi.Resolution.Proxies.UnregisteredServiceResolverProxy"/> class.
        /// </summary>
        /// <param name="proxiedResolver">Proxied resolver.</param>
        /// <param name="registrationResolver">Registration resolver.</param>
        /// <param name="unregisteredRegistrationProvider">Unregistered registration provider.</param>
        /// <param name="cache">The service cache.</param>
        /// <param name="registry">The service registry</param>
        public UnregisteredServiceResolverProxy(IResolver proxiedResolver,
                                                IResolvesRegistrations registrationResolver,
                                                IServiceRegistrationProvider unregisteredRegistrationProvider,
                                                ICachesResolvedServiceInstances cache,
                                                IRegistersServices registry)
            : base(proxiedResolver)
        {
            if (registry == null)
            {
                throw new ArgumentNullException(nameof(registry));
            }
            if (unregisteredRegistrationProvider == null)
            {
                throw new ArgumentNullException(nameof(unregisteredRegistrationProvider));
            }
            if (registrationResolver == null)
            {
                throw new ArgumentNullException(nameof(registrationResolver));
            }

            this.cache = cache;
            this.registrationResolver             = registrationResolver;
            this.unregisteredRegistrationProvider = unregisteredRegistrationProvider;
            this.registry = registry;
        }
예제 #7
0
        /// <summary>
        /// Utility method resolves the type and logs and returns success.
        /// </summary>
        private static bool tryResolve(
            Type targetType,
            out object result,
            ServiceConstructorRequest request,
            IServiceRegistrationProvider serviceProvider,
            Func <Type, object> instanceProvider,
            bool logMustResolve)
        {
            bool CheckResult(object service, string sourceName, out object successResult)
            {
                if (targetType.IsInstanceOfType(service))
                {
                    request.TraceStack.Add($"{sourceName} resolved '{targetType.GetFriendlyFullName()}'.");
                    successResult = service;
                    return(true);
                }
                successResult = null;
                return(false);
            }

            if (instanceProvider != null)
            {
                if (CheckResult(instanceProvider(targetType), "InstanceProvider Func", out result))
                {
                    return(true);
                }
            }
            if (CheckResult(serviceProvider.GetService(targetType, request), nameof(IServiceProvider), out result))
            {
                return(true);
            }
            if (serviceProvider.ParentServiceProvider
                is IServiceRegistrationProvider parentServiceRegistrationProvider)
            {
                if (CheckResult(
                        parentServiceRegistrationProvider.GetService(targetType, request),
                        nameof(IServiceRegistrationProvider.ParentServiceProvider),
                        out result))
                {
                    return(true);
                }
            }
            else
            {
                if (CheckResult(
                        serviceProvider.ParentServiceProvider?.GetService(targetType),
                        nameof(IServiceRegistrationProvider.ParentServiceProvider),
                        out result))
                {
                    return(true);
                }
            }
            if (logMustResolve)
            {
                request.TraceStack.Add($"Did not resolve '{targetType.GetFriendlyFullName()}'.");
            }
            return(false);
        }
        public void Resolve_can_create_dictionary_of_instances_by_enum_values([Frozen, ResolvesToFailure] IResolver proxiedResolver,
                                                                              [Frozen] IDictionaryFactory dictionaryFactory,
                                                                              [Frozen] IServiceRegistrationProvider registrationProvider,
                                                                              NamedInstanceDictionaryResolverProxy sut,
                                                                              ResolutionRequest request,
                                                                              SampleEnum[] names,
                                                                              ResolutionPath path)
        {
            // Arrange
            var serviceType = request.ServiceType;
            var keyType     = typeof(SampleEnum);
            var valueType   = typeof(ISampleService);

            Mock.Get(dictionaryFactory)
            .Setup(x => x.IsGenericDictionaryType(serviceType))
            .Returns(true);
            Mock.Get(dictionaryFactory)
            .Setup(x => x.GetKeyType(serviceType))
            .Returns(keyType);
            Mock.Get(dictionaryFactory)
            .Setup(x => x.GetValueType(serviceType))
            .Returns(valueType);
            Mock.Get(dictionaryFactory)
            .Setup(x => x.Create(keyType, valueType))
            .Returns(() => new Dictionary <SampleEnum, ISampleService>());
            var registrations = names
                                .Select(x => x.ToString())
                                .Select(x => Mock.Of <IServiceRegistration>(r => r.Name == x && r.ServiceType == valueType))
                                .ToArray();

            Mock.Get(registrationProvider)
            .Setup(x => x.GetAll(valueType))
            .Returns(registrations);
            Mock.Get(proxiedResolver)
            .Setup(x => x.Resolve(It.Is <ResolutionRequest>(r => r.ServiceType == valueType)))
            .Returns((ResolutionRequest r) => ResolutionResult.Success(path, new SampleServiceImplementationOne()));

            // Act
            var result = sut.Resolve(request);

            // Assert
            Mock.Get(proxiedResolver)
            .Verify(x => x.Resolve(It.Is <ResolutionRequest>(r => r.ServiceType == valueType)), Times.Exactly(names.Length));
            foreach (var name in names.Select(x => x.ToString()).ToArray())
            {
                Mock.Get(proxiedResolver)
                .Verify(x => x.Resolve(It.Is <ResolutionRequest>(r => r.Name == name)), Times.Once);
            }
            Assert.That(result.IsSuccess, Is.True);
            Assert.That(result.ResolvedObject, Is.InstanceOf <IDictionary <SampleEnum, ISampleService> >());
            var resolvedObject = (IDictionary <SampleEnum, ISampleService>)result.ResolvedObject;

            Assert.That(resolvedObject, Has.Count.EqualTo(names.Length));
        }
예제 #9
0
        /// <summary>
        /// Initializes a new instance of the
        /// <see cref="T:CSF.FlexDi.Resolution.Proxies.UnregisteredServiceResolverProxyFactory"/> class.
        /// </summary>
        /// <param name="registrationResolver">Registration resolver.</param>
        /// <param name="unregisteredRegistrationProvider">Unregistered registration provider.</param>
        public UnregisteredServiceResolverProxyFactory(IResolvesRegistrations registrationResolver,
                                                       IServiceRegistrationProvider unregisteredRegistrationProvider = null)
        {
            if (registrationResolver == null)
            {
                throw new ArgumentNullException(nameof(registrationResolver));
            }

            this.registrationResolver             = registrationResolver;
            this.unregisteredRegistrationProvider = unregisteredRegistrationProvider;
        }
예제 #10
0
        Resolver GetSut(IServiceRegistrationProvider provider, IServiceRegistrationProvider unregisteredProvider = null)
        {
            var instanceCreator = new Mock <ICreatesObjectInstances>();

            instanceCreator
            .Setup(x => x.CreateFromFactory(It.IsAny <IFactoryAdapter>(),
                                            It.IsAny <ResolutionPath>(),
                                            It.IsAny <IServiceRegistration>()))
            .Returns((IFactoryAdapter a, ResolutionPath p, IServiceRegistration r) => CreateInstance(a, p, r));

            return(new Resolver(provider, instanceCreator.Object));
        }
예제 #11
0
        public DefaultServiceRegister(
            IServiceRegistrationProvider registrationProvider,
            IServiceProvider serviceProvider,
            IOptions <RpcServerOptions> options, ILogger <DefaultServiceRegister> logger)
        {
            this._registrationProvider = registrationProvider;
            this._serviceProvider      = serviceProvider;
            this._logger       = logger;
            this._optionValues = options.Value;

            this._localBindAddress = new IPEndPoint(GetBindAddress(), this._optionValues.Port);
        }
예제 #12
0
파일: Resolver.cs 프로젝트: csf-dev/FlexDi
        /// <summary>
        /// Initializes a new instance of the <see cref="T:CSF.FlexDi.Resolution.Resolver"/> class.
        /// </summary>
        /// <param name="registrationProvider">Registration provider.</param>
        /// <param name="instanceCreator">Instance creator.</param>
        public Resolver(IServiceRegistrationProvider registrationProvider,
                        ICreatesObjectInstances instanceCreator)
        {
            if (instanceCreator == null)
            {
                throw new ArgumentNullException(nameof(instanceCreator));
            }
            if (registrationProvider == null)
            {
                throw new ArgumentNullException(nameof(registrationProvider));
            }

            this.registrationProvider = registrationProvider;
            this.instanceCreator      = instanceCreator;
        }
        /// <summary>
        /// Initializes a new instance of the
        /// <see cref="T:CSF.FlexDi.Resolution.Proxies.NamedInstanceDictionaryResolverProxy"/> class.
        /// </summary>
        /// <param name="proxiedResolver">Proxied resolver.</param>
        /// <param name="registrationAccessor">Registration accessor.</param>
        /// <param name="dictionaryFactory">Dictionary factory.</param>
        public NamedInstanceDictionaryResolverProxy(IResolver proxiedResolver,
                                                    IServiceRegistrationProvider registrationAccessor,
                                                    IDictionaryFactory dictionaryFactory) : base(proxiedResolver)
        {
            if (dictionaryFactory == null)
            {
                throw new ArgumentNullException(nameof(dictionaryFactory));
            }
            if (registrationAccessor == null)
            {
                throw new ArgumentNullException(nameof(registrationAccessor));
            }

            this.registrationAccessor = registrationAccessor;
            this.dictionaryFactory    = dictionaryFactory;
        }
예제 #14
0
        /// <summary>
        /// Coordinates the disposal of all disposable service/component instances within the given cache.
        /// </summary>
        /// <param name="registrationProvider">Registration provider.</param>
        /// <param name="instanceCache">A cache which provides access to the component instances.</param>
        public void DisposeInstances(IServiceRegistrationProvider registrationProvider,
                                     ICachesResolvedServiceInstances instanceCache)
        {
            if (registrationProvider == null)
            {
                throw new ArgumentNullException(nameof(registrationProvider));
            }
            if (instanceCache == null)
            {
                throw new ArgumentNullException(nameof(instanceCache));
            }

            var registrationsToDispose = GetRegistrationsToDispose(registrationProvider);

            Dispose(registrationsToDispose, instanceCache);
        }
예제 #15
0
        public void DisposeInstances_does_not_dispose_non_disposable_objects(IServiceRegistrationProvider registrations,
                                                                             ICachesResolvedServiceInstances cache,
                                                                             ServiceInstanceDisposer sut,
                                                                             IServiceRegistration registration,
                                                                             object nonDisposable)
        {
            // Arrange
            Mock.Get(registration).SetupGet(x => x.DisposeWithContainer).Returns(false);
            Mock.Get(registration).SetupGet(x => x.Cacheable).Returns(true);
            Mock.Get(registrations).Setup(x => x.GetAll()).Returns(new [] { registration });
            object obj = nonDisposable;

            Mock.Get(cache)
            .Setup(x => x.TryGet(registration, out obj))
            .Callback(() => obj = nonDisposable)
            .Returns(true);

            // Act
            Assert.That(() => sut.DisposeInstances(registrations, cache), Throws.Nothing);
        }
예제 #16
0
        public void DisposeInstances_does_not_dispose_non_cached_instances(IServiceRegistrationProvider registrations,
                                                                           ICachesResolvedServiceInstances cache,
                                                                           ServiceInstanceDisposer sut,
                                                                           IServiceRegistration registration,
                                                                           IDisposable disposable)
        {
            // Arrange
            Mock.Get(registration).SetupGet(x => x.DisposeWithContainer).Returns(true);
            Mock.Get(registration).SetupGet(x => x.Cacheable).Returns(true);
            Mock.Get(registrations).Setup(x => x.GetAll()).Returns(new [] { registration });
            object obj = disposable;

            Mock.Get(cache)
            .Setup(x => x.TryGet(registration, out obj))
            .Returns(false);

            // Act
            sut.DisposeInstances(registrations, cache);

            // Assert
            Mock.Get(disposable).Verify(x => x.Dispose(), Times.Never);
        }
예제 #17
0
 /// <summary>
 /// Constructor. Notice that the <paramref name="factory"/> is optional:
 /// <see cref="IsImplementationContainerCreated"/> is
 /// set based on this argument by default.
 /// </summary>
 /// <param name="serviceProvider">Required.</param>
 /// <param name="serviceType">Required.</param>
 /// <param name="implementationType">Required.</param>
 /// <param name="isSingleton">Required.</param>
 /// <param name="factory">OPTIONAL: if null, the <see cref="ServiceConstructorMethods"/>
 /// constructs the object. Note also that <see cref="IsImplementationContainerCreated"/>
 /// is set true by default if this is null; and is set false by default
 /// if this is not null.</param>
 /// <param name="isImplementationContainerCreated">Specifies the value
 /// for <see cref="IsImplementationContainerCreated"/>;
 /// which determines the disposal policy: this class ONLY disposes singletons
 /// marked as <c>IsImplementationContainerCreated</c> (and always disposes
 /// such instances). This value is nullable: if null, it will be set true
 /// if the <c>factory</c> is null; and otherwise false.</param>
 /// <exception cref="ArgumentNullException"/>
 /// <exception cref="ArgumentException">If the <paramref name="implementationType"/>
 /// does not extend the <paramref name="serviceType"/></exception>
 public ServiceRegistration(
     IServiceRegistrationProvider serviceProvider,
     Type serviceType,
     Type implementationType,
     bool isSingleton,
     Func <IServiceProvider, object> factory = null,
     bool?isImplementationContainerCreated   = null)
 {
     this.serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
     ServiceType          = serviceType ?? throw new ArgumentNullException(nameof(serviceType));
     ImplementationType   = implementationType ?? throw new ArgumentNullException(nameof(implementationType));
     if (!serviceType.IsAssignableFrom(implementationType))
     {
         throw new ArgumentException(
                   $"Implementation type '{implementationType.GetFriendlyFullName()}'"
                   + $" is not assignable to service type '{serviceType.GetFriendlyFullName()}'",
                   nameof(implementationType));
     }
     IsSingleton  = isSingleton;
     this.factory = factory;
     IsImplementationContainerCreated = isImplementationContainerCreated ?? (factory == null);
 }
예제 #18
0
        public void Dispose()
        {
            List <ServiceRegistration> disposeRegistrations;

            lock (registrations) {
                disposeRegistrations = DisposeRegistrationsWithContainer
                                                ? registrations.Values.ToList()
                                                : null;
                registrations.Clear();
                parentServiceRegistrationProvider = null;
                parentServiceProvider             = null;
            }
            if (disposeRegistrations == null)
            {
                return;
            }
            disposeRegistrations.Sort(DateComparer);
            disposeRegistrations.Sort(DependencyComparer);
            disposeRegistrations.Sort(DependantComparer);
            foreach (ServiceRegistration disposeRegistration in disposeRegistrations)
            {
                disposeRegistration.Dispose();
            }
예제 #19
0
        public static bool TryConstruct(
            this IServiceProvider serviceProvider,
            Type targetType,
            out object service,
            ITrace logger = null,
            Func <Type, object> instanceProvider = null,
            bool tryConstructArguments           = false,
            bool?requireAttributes = null,
            params Type[] attributeTypes)
        {
            IServiceRegistrationProvider serviceRegistrationProvider
                = serviceProvider as IServiceRegistrationProvider
                  ?? new ServiceRegistrationProviderWrapper(serviceProvider);

            return(ServiceConstructorMethods.TryConstruct(
                       targetType,
                       out service,
                       new ServiceConstructorRequest(logger),
                       serviceRegistrationProvider,
                       instanceProvider,
                       tryConstructArguments,
                       requireAttributes,
                       attributeTypes));
        }
        IDictionary <ServiceRegistrationKey, IServiceRegistration> GetNonConflictingRegistrations(IEnumerable <ServiceRegistrationKey> alreadyFound,
                                                                                                  IServiceRegistrationProvider provider,
                                                                                                  Type serviceTypeFilter)
        {
            if (alreadyFound == null)
            {
                throw new ArgumentNullException(nameof(alreadyFound));
            }
            if (provider == null)
            {
                throw new ArgumentNullException(nameof(provider));
            }

            var candidates = (serviceTypeFilter != null)? provider.GetAll(serviceTypeFilter) : provider.GetAll();

            if (candidates == null)
            {
                candidates = new IServiceRegistration[0];
            }

            return((from registration in candidates
                    let key = ServiceRegistrationKey.ForRegistration(registration)
                              where !alreadyFound.Contains(key)
                              select new { Registration = registration, Key = key })
                   .ToDictionary(k => k.Key, v => v.Registration));
        }
예제 #21
0
 public static bool TryConstruct(
     Type targetType,
     out object service,
     ServiceConstructorRequest request,
     IServiceRegistrationProvider serviceProvider,
     Func <Type, object> instanceProvider = null,
     bool tryConstructArguments           = false,
     bool?requireConstructorAttributes    = null,
     IReadOnlyCollection <Type> constructorAttributeTypes = null)
 {
     if (targetType == null)
     {
         throw new ArgumentNullException(nameof(targetType));
     }
     if (request == null)
     {
         throw new ArgumentNullException(nameof(request));
     }
     if (serviceProvider == null)
     {
         throw new ArgumentNullException(nameof(serviceProvider));
     }
     if ((constructorAttributeTypes == null) ||
         (constructorAttributeTypes.Count == 0))
     {
         constructorAttributeTypes = new[] { typeof(ServiceProviderConstructorAttribute) }
     }
     ;
     if (request.ConstructingTypes.Contains(targetType))
     {
         request.TraceStack.Add(
             "Found a recursive constructor dependency"
             + $": '{targetType.GetFriendlyFullName()}'"
             + " ... cannot continue.");
         service = null;
         return(false);
     }
     request.ConstructingTypes.Add(targetType);
     request.Logger.Verbose("Constructing {0}.", targetType.GetFriendlyFullName());
     if (ServiceConstructorMethods.invokeMember(
             ServiceConstructorMethods.findConstructors(
                 targetType,
                 requireConstructorAttributes,
                 constructorAttributeTypes,
                 request.TraceStack),
             false,
             null,
             out service,
             request,
             serviceProvider,
             instanceProvider,
             tryConstructArguments,
             requireConstructorAttributes,
             constructorAttributeTypes,
             false))
     {
         request.Logger.Verbose(
             "Construct result for '{0}' is true: '{1}'.",
             targetType.GetFriendlyFullName(),
             service.GetType().GetFriendlyFullName());
         request.ConstructingTypes.Remove(targetType);
         return(true);
     }
     request.Logger.Warning("Construct result for '{0}' is false.", targetType.GetFriendlyFullName());
     request.ConstructingTypes.Remove(targetType);
     return(false);
 }
예제 #22
0
        private static bool invokeMember(
            IEnumerable <MethodBase> members,
            bool isMethod,
            object methodTarget,
            out object newInstance,
            ServiceConstructorRequest request,
            IServiceRegistrationProvider serviceProvider,
            Func <Type, object> instanceProvider,
            bool tryConstructArguments,
            bool?requireConstructorAttributes,
            IReadOnlyCollection <Type> constructorAttributeTypes,
            bool isRecursed)
        {
            newInstance = null;
            bool success = false;

            foreach (MethodBase methodBase in members)
            {
                ParameterInfo[] parameters = methodBase.GetParameters();
                if (parameters.Length == 0)
                {
                    success = isMethod
                                                        ? ServiceConstructorMethods.tryInvokeMethod(
                        methodTarget,
                        (MethodInfo)methodBase,
                        new object[0],
                        request.TraceStack)
                                                        : ServiceConstructorMethods.tryInvokeConstructor(
                        (ConstructorInfo)methodBase,
                        new object[0],
                        out newInstance,
                        request.TraceStack);
                    break;
                }
                List <object> arguments = new List <object>(parameters.Length);
                foreach (ParameterInfo parameterInfo in parameters)
                {
                    if (ServiceConstructorMethods.tryResolve(
                            parameterInfo.ParameterType,
                            out object parameterResult,
                            request,
                            serviceProvider,
                            instanceProvider,
                            !tryConstructArguments))
                    {
                        arguments.Add(parameterResult);
                        continue;
                    }
                    if (tryConstructArguments)
                    {
                        if (request.ConstructingTypes.Contains(parameterInfo.ParameterType))
                        {
                            request.TraceStack.Add(
                                "Found a recursive constructor dependency"
                                + $": '{parameterInfo.ParameterType.GetFriendlyFullName()}'"
                                + " ... cannot continue.");
                            break;
                        }
                        request.ConstructingTypes.Add(parameterInfo.ParameterType);
                        bool argumentSuccess
                            = ServiceConstructorMethods.invokeMember(
                                  ServiceConstructorMethods.findConstructors(
                                      parameterInfo.ParameterType,
                                      requireConstructorAttributes,
                                      constructorAttributeTypes,
                                      request.TraceStack),
                                  false,
                                  null,
                                  out object argumentResult,
                                  request,
                                  serviceProvider,
                                  instanceProvider,
                                  true,
                                  requireConstructorAttributes,
                                  constructorAttributeTypes,
                                  true);
                        request.ConstructingTypes.Remove(parameterInfo.ParameterType);
                        if (argumentSuccess)
                        {
                            arguments.Add(argumentResult);
                            continue;
                        }
                    }
                    if (parameterInfo.HasDefaultValue)
                    {
                        request.TraceStack.Add(
                            $"Parameter '{parameterInfo.ParameterType.GetFriendlyFullName()}' has default value.");
                        arguments.Add(parameterInfo.DefaultValue);
                    }
                    else
                    {
                        break;
                    }
                }
                if ((arguments.Count != parameters.Length) ||
                    (isMethod
                                                                ? !ServiceConstructorMethods.tryInvokeMethod(
                         methodTarget,
                         (MethodInfo)methodBase,
                         arguments.ToArray(),
                         request.TraceStack)
                                                                : !ServiceConstructorMethods.tryInvokeConstructor(
                         (ConstructorInfo)methodBase,
                         arguments.ToArray(),
                         out newInstance,
                         request.TraceStack)))
                {
                    continue;
                }
                request.Dependencies.TryAddRange(
                    methodBase.DeclaringType,
                    parameters.Select(parameter => parameter.ParameterType));
                success = true;
                break;
            }
            if (isRecursed)
            {
                return(success);
            }
            if (success)
            {
                if (request.Logger.IsVerbose())
                {
                    request.Logger.Verbose(GetTraceMessage());
                }
            }
            else
            {
                if (request.Logger.IsInfo())
                {
                    request.Logger.Info(GetTraceMessage());
                }
            }
            string GetTraceMessage()
            {
                string        separator = $"{Environment.NewLine}    ";
                StringBuilder sb        = request.TraceStack.ToConcatenatedString(null, separator);

                if (sb.Length != 0)
                {
                    sb.Insert(0, "    ");
                }
                return(sb.ToString());
            }

            return(success);
        }
예제 #23
0
        /// <summary>
        /// Gets a collection of the service/component registrations which are eligible for disposal.
        /// </summary>
        /// <returns>The registrations to dispose.</returns>
        /// <param name="registrationProvider">Registration provider.</param>
        protected virtual IReadOnlyCollection <IServiceRegistration> GetRegistrationsToDispose(IServiceRegistrationProvider registrationProvider)
        {
            if (registrationProvider == null)
            {
                throw new ArgumentNullException(nameof(registrationProvider));
            }

            return(registrationProvider
                   .GetAll()
                   .Where(x => x.Cacheable && x.DisposeWithContainer)
                   .ToArray());
        }
        public void Resolve_resolves_unregistered_service_when_resolution_is_unsuccesful([Frozen, ResolvesToFailure] IResolver proxiedResolver,
                                                                                         [Frozen] IResolvesRegistrations registrationResolver,
                                                                                         [Frozen] IServiceRegistrationProvider unregisteredRegistrationProvider,
                                                                                         UnregisteredServiceResolverProxy sut,
                                                                                         ResolutionPath path,
                                                                                         ResolutionRequest request,
                                                                                         ResolutionResult resolutionResult,
                                                                                         IServiceRegistration registration)
        {
            // Arrange
            Mock.Get(proxiedResolver)
            .Setup(x => x.Resolve(request))
            .Returns(ResolutionResult.Failure(path));
            Mock.Get(unregisteredRegistrationProvider)
            .Setup(x => x.Get(request))
            .Returns(registration);
            Mock.Get(registrationResolver)
            .Setup(x => x.Resolve(request, registration))
            .Returns(resolutionResult);

            // Act
            var result = sut.Resolve(request);

            // Assert
            Assert.That(result, Is.SameAs(resolutionResult));
        }