예제 #1
0
        private ConstructorInfo GetSingleConstructor(ServiceImplementationInfo serviceImplementationInfo, Type expectedParameterType)
        {
            var argumentTypesDoNotMatchMessage = string.Format(
                " The public constructor must at least accept an argument of type '{0}'.",
                expectedParameterType);

            var exceptionMessage = string.Format(
                "Type '{0}' cannot be instantiated. The type must have exactly one public constructor.{1}",
                serviceImplementationInfo.ImplementationType,
                expectedParameterType == null ? "" : argumentTypesDoNotMatchMessage);

            var constructors = serviceImplementationInfo.ImplementationType.GetConstructors();

            if (constructors.Length != 1)
            {
                throw new InvalidOperationException(exceptionMessage);
            }

            var constructor = constructors.First();

            if (expectedParameterType != null && constructor.GetParameters().Count(p => p.ParameterType == expectedParameterType) != 1)
            {
                throw new InvalidOperationException(exceptionMessage);
            }

            return(constructor);
        }
예제 #2
0
        private Func <object> CreateInstanceFactory(
            Type serviceType,
            ServiceImplementationInfo serviceImplementationInfo,
            Func <Func <object>, object> decoratorChain)
        {
            Func <object> instanceFactory;

            if (serviceImplementationInfo.Factory == null)
            {
                var isCompound            = serviceImplementationInfo.RegistrationType == RegistrationType.Compound;
                var expectedParameterType = isCompound ? typeof(IEnumerable <>).MakeGenericType(serviceType) : null;
                var ctorInfo = GetSingleConstructor(serviceImplementationInfo, expectedParameterType);
                instanceFactory = CreateInstanceFactoryFromConstructorInfo(ctorInfo, isCompound);
            }
            else
            {
                instanceFactory = serviceImplementationInfo.Factory;
            }

            Func <object> decoratedFactory = () => decoratorChain(instanceFactory);

            switch (serviceImplementationInfo.Lifetime)
            {
            case LifetimeKind.Singleton:
                var factoryContainer = new Lazy <object> (decoratedFactory, LazyThreadSafetyMode.ExecutionAndPublication);
                return(() => factoryContainer.Value);

            default:
                return(decoratedFactory);
            }
        }
        //as extension for IServiceConfigurationRegistry, or drop if did not exist before feature branch or if no longer needed. Obsolete if old API was used in many projects
        /// <summary>
        /// Registers factories for the specified <typeparamref name="TService"/>.
        /// The factories are subsequently invoked whenever instances for the <typeparamref name="TService"/> is requested.
        /// </summary>
        /// <typeparam name="TService">The service type to register the factories for.</typeparam>
        /// <param name="serviceConfigurationRegistry">The <see cref="IServiceConfigurationRegistry"/> with which to register the <typeparamref name="TService"/>.</param>
        /// <param name="instanceFactories">The instance factories to use when resolving instances for the <typeparamref name="TService"/>. These factories
        /// must return non-null instances implementing the <typeparamref name="TService"/>, otherwise an <see cref="ActivationException"/> is thrown
        /// when an instance of <typeparamref name="TService"/> is requested.</param>
        /// <exception cref="InvalidOperationException">Factories have already been registered or an instance of the <typeparamref name="TService"/> has
        /// already been retrieved. Registering factories or concrete implementations can only be done before any instances are retrieved.</exception>
        public static void RegisterMultiple <TService> (this IServiceConfigurationRegistry serviceConfigurationRegistry, IEnumerable <Func <TService> > instanceFactories)
            where TService : class
        {
            ArgumentUtility.CheckNotNull("serviceConfigurationRegistry", serviceConfigurationRegistry);
            ArgumentUtility.CheckNotNull("instanceFactories", instanceFactories);

            var serviceConfigurationEntry = new ServiceConfigurationEntry(
                typeof(TService),
                instanceFactories.Select(f => ServiceImplementationInfo.CreateMultiple(f, LifetimeKind.InstancePerDependency)));

            serviceConfigurationRegistry.Register(serviceConfigurationEntry);
        }
        //TODO RM-5506: register api:
        //registerSingle(this IServiceConfigurationRegistry registry, Type serviceType, Type implementationType, Type[] decoratorTypes = null, LifetimeKind = Instance)
        //registerMultiple(this IServiceConfigurationRegistry registry, Type serviceType, Type[] implementationType, Type[] decoratorTypes = null, LifetimeKind = Instance)
        //registerCompound(this IServiceConfigurationRegistry registry, Type serviceType, Type compoundType, Type[] implementationTypes, Type[] decoratorTypes = null, LifetimeKind = Instance)
        //registerSingle(this IServiceConfigurationRegistry registry, Type serviceType, Func<object> instanceFactory, Type[] decoratorTypes = null, LifetimeKind = Instance
        //registerMultiple(this IServiceConfigurationRegistry registry, Type serviceType, Func<object>[] instanceFactories, Type[] decoratorTypes = null, LifetimeKind = Instance
        //registerCompound(this IServiceConfigurationRegistry registry, Type serviceType, Type compoundType, Func<object>[] instanceFactories, Type[] decoratorTypes = null, LifetimeKind = Instance

        /// <summary>
        /// Registers factories for the specified <typeparamref name="TService"/>.
        /// The factories are subsequently invoked whenever instances for the <typeparamref name="TService"/> is requested.
        /// </summary>
        /// <typeparam name="TService">The service type to register the factories for.</typeparam>
        /// <param name="serviceConfigurationRegistry">The <see cref="IServiceConfigurationRegistry"/> with which to register the <typeparamref name="TService"/>.</param>
        /// <param name="instanceFactory">The instance factory to use when resolving instances for the <typeparamref name="TService"/>. This factory
        /// must return a non-null instance implementing the <typeparamref name="TService"/>, otherwise an <see cref="ActivationException"/> is thrown
        /// when an instance of <typeparamref name="TService"/> is requested.</param>
        /// <exception cref="InvalidOperationException">Factories have already been registered or an instance of the <typeparamref name="TService"/> has
        /// already been retrieved. Registering factories or concrete implementations can only be done before any instances are retrieved.</exception>
        public static void RegisterSingle <TService> (this IServiceConfigurationRegistry serviceConfigurationRegistry, Func <TService> instanceFactory)
            where TService : class
        {
            ArgumentUtility.CheckNotNull("serviceConfigurationRegistry", serviceConfigurationRegistry);
            ArgumentUtility.CheckNotNull("instanceFactory", instanceFactory);

            var serviceConfigurationEntry = new ServiceConfigurationEntry(
                typeof(TService),
                ServiceImplementationInfo.CreateSingle(instanceFactory, LifetimeKind.InstancePerDependency));

            serviceConfigurationRegistry.Register(serviceConfigurationEntry);
        }
        /// <summary>
        /// Registers a concrete implementation for the specified <paramref name="serviceType"/>.
        /// </summary>
        /// <param name="serviceConfigurationRegistry">The <see cref="IServiceConfigurationRegistry"/> with which to register the <paramref name="serviceType"/>.</param>
        /// <param name="serviceType">The service type to register a concrete implementation for.</param>
        /// <param name="concreteImplementationType">The type of the concrete implementation to be instantiated when an instance of the
        /// <paramref name="serviceType"/> is retrieved.</param>
        /// <param name="lifetime">The lifetime of the instances.</param>
        /// <param name="registrationType">The registration type of the implementation.</param>
        /// <exception cref="InvalidOperationException">An instance of the <paramref name="serviceType"/> has already been retrieved. Registering factories
        /// or concrete implementations can only be done before any instances are retrieved.</exception>
        public static void Register(this IServiceConfigurationRegistry serviceConfigurationRegistry, Type serviceType, Type concreteImplementationType, LifetimeKind lifetime, RegistrationType registrationType = RegistrationType.Single)
        {
            ArgumentUtility.CheckNotNull("serviceConfigurationRegistry", serviceConfigurationRegistry);
            ArgumentUtility.CheckNotNull("serviceType", serviceType);
            ArgumentUtility.CheckNotNull("concreteImplementationType", concreteImplementationType);

            var serviceImplemetation = new ServiceImplementationInfo(concreteImplementationType, lifetime, registrationType);
            ServiceConfigurationEntry serviceConfigurationEntry;

            try
            {
                serviceConfigurationEntry = new ServiceConfigurationEntry(serviceType, serviceImplemetation);
            }
            catch (ArgumentException ex)
            {
                throw new ArgumentException("Implementation type must implement service type.", "concreteImplementationType", ex);
            }

            serviceConfigurationRegistry.Register(serviceConfigurationEntry);
        }