Exemple #1
0
        /// <summary>
        ///     Tracks the specified <paramref name="instance"/> for disposation.
        /// </summary>
        /// <param name="resolveContext">the resolver context from which the service was resolved</param>
        /// <param name="instance">the instance to track</param>
        /// <param name="scopeKey">
        ///     the <paramref name="scopeKey"/> the instance was created for; if
        ///     <see langword="null"/> then the scope is global.
        /// </param>
        public void TrackInstance(ServiceResolveContext resolveContext, object instance, object scopeKey = null)
        {
            // check if the tracking of disposable transients is enabled
            if (!resolveContext.Resolver.TrackDisposableTransients)
            {
                return;
            }

            // The instances in the lifetime are tracked to dispose them, so we need only to track
            // disposable / asynchronously disposable objects.

#if SUPPORTS_ASYNC_DISPOSABLE
            // check if the instance does not inherit from IDisposable or IAsyncDisposable, then
            // there is no need to track the service instance since the transient lifetime always
            // re-creates services
            if (!(instance is IDisposable || instance is IAsyncDisposable))
            {
                // there is no need to track the instance
                return;
            }

            // acquire lock
            _trackerLock.Wait();

            // ensure the lock is released even if an exception is thrown
            try
            {
                // track instance
                _tracker.Add(instance);
            }
            finally
            {
                // release lock and let other threads continue
                _trackerLock.Release();
            }
#else // SUPPORTS_ASYNC_DISPOSABLE
            if (instance is IDisposable disposable)
            {
                lock (_trackerLock)
                {
                    // add instance to tracking list
                    _tracker.Add(disposable);
                }
            }
#endif // !SUPPORTS_ASYNC_DISPOSABLE
        }
Exemple #2
0
        /// <summary>
        ///     Creates a new instance of the specified service type (in <paramref name="context"/>).
        /// </summary>
        /// <param name="implementationType">the type of the implementation to construct</param>
        /// <param name="context">the resolve context</param>
        /// <returns>the service instance</returns>
        /// <exception cref="ArgumentNullException">
        ///     thrown if the specified <paramref name="implementationType"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     thrown if the specified <paramref name="context"/> is <see langword="null"/>.
        /// </exception>
        public static object Resolve(Type implementationType, ServiceResolveContext context)
        {
            // TODO add parameter for service construction mode

            if (implementationType is null)
            {
                throw new ArgumentNullException(nameof(implementationType));
            }

            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            // resolve constructors
#if SUPPORTS_REFLECTION
            var availableConstructors = implementationType.GetConstructors();
#else // SUPPORTS_REFLECTION
            var availableConstructors = implementationType.GetTypeInfo().DeclaredConstructors;
#endif // !SUPPORTS_REFLECTION

            // resolve constructor for the type
            var constructor = ResolveConstructor(context, availableConstructors, implementationType);

#if DEBUG
            // trace output
            context.TraceBuilder.AppendConstructorResolve(implementationType, constructor);
#endif // DEBUG

            // get constructor parameters and create array holding the parameters for the constructor
            var constructorParameters = constructor.GetParameters();
            var invocationParameters  = new object[constructorParameters.Length];

            // resolve services for the constructor
            for (var index = 0; index < constructorParameters.Length; index++)
            {
                // the type of the service being resolved
                var serviceType = constructorParameters[index].ParameterType;

                // resolve service and add to constructor parameter invocation list
                invocationParameters[index] = context.Resolver.Resolve(serviceType, context);
            }

            // invoke constructor and constructor type
            return(constructor.Invoke(invocationParameters));
        }
        /// <summary>
        ///     Tries to resolve an object from the manager.
        /// </summary>
        /// <param name="resolveContext">the current resolver context</param>
        /// <param name="scopeKey">
        ///     the <paramref name="scopeKey"/> the instance was created for; if
        ///     <see langword="null"/> then the scope is global.
        /// </param>
        /// <returns>the resolved service; or default if the service could not be resolved</returns>
        public object Resolve(ServiceResolveContext resolveContext, object scopeKey = null)
        {
            // create the key for resolving the type from the scope
            var key = new KeyValuePair <Type, object>(resolveContext.ServiceType, scopeKey);

            return(_services.TryGetValue(key, out var service) ? service : default);
Exemple #4
0
 /// <summary>
 ///     Initializes a new instance of the <see cref="ResolverException"/> class.
 /// </summary>
 /// <param name="message">the message</param>
 /// <param name="context">the current resolver context</param>
 public ResolverException(string message, ServiceResolveContext context)
     : this(BuildMessage(message, context)) => Context = context;
 public object Create(ServiceResolveContext context) => throw new NotImplementedException();
 protected override object CreateService(ServiceResolveContext context) => Reflector.Resolve <TImplementation>(context);
        /// <summary>
        ///     Creates the instance.
        /// </summary>
        /// <param name="context">the current resolver context</param>
        /// <returns>the instance</returns>
#if NO_REFLECTION
        protected override object CreateService(ServiceResolveContext context) => Activator.CreateInstance <TImplementation>();
Exemple #8
0
 /// <summary>
 ///     Tries to resolve an object from the manager.
 /// </summary>
 /// <param name="resolveContext">the current resolver context</param>
 /// <param name="scopeKey">
 ///     the <paramref name="scopeKey"/> the instance was created for; if
 ///     <see langword="null"/> then the scope is global.
 /// </param>
 /// <returns>the resolved service; or default if the service could not be resolved</returns>
 public object Resolve(ServiceResolveContext resolveContext, object scopeKey = null)
 {
     // The transient lifetime always re-creates services.
     return(null);
 }
Exemple #9
0
 public static TImplementation Resolve <TImplementation>(ServiceResolveContext context)
 => (TImplementation)Resolve(typeof(TImplementation), context);
Exemple #10
0
        /// <summary>
        ///     Resolves the matching constructor for the specified
        ///     <paramref name="implementationType"/> with respecting the specified <paramref name="constructionMode"/>.
        /// </summary>
        /// <param name="context">the current resolver context</param>
        /// <param name="availableConstructors">
        ///     an enumerable that enumerates through the available constructors for the specified <paramref name="implementationType"/>.
        /// </param>
        /// <param name="implementationType">
        ///     the type of the service implementation to resolve the constructor for
        /// </param>
        /// <param name="constructionMode">the service construction mode.</param>
        /// <returns>the constructor chosen fro the specified <paramref name="implementationType"/></returns>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     thrown if the specified <paramref name="constructionMode"/> is unsupported or not
        ///     defined in the <see cref="ServiceConstructionMode"/> enumeration.
        /// </exception>
        /// <exception cref="ResolverException">
        ///     thrown if no passable constructor was found for the specified <paramref name="implementationType"/>
        /// </exception>
        public static ConstructorInfo ResolveConstructor(ServiceResolveContext context,
                                                         IEnumerable <ConstructorInfo> availableConstructors, Type implementationType,
                                                         ServiceConstructionMode constructionMode = ServiceConstructionMode.Mixed)
        {
            // check if no constructors are available
            if (!availableConstructors.Any())
            {
                return(null);
            }

            // check whether the mode is mixed
            if (context.ConstructionMode == ServiceConstructionMode.Mixed)
            {
                // iterate through all constructors
                foreach (var constructor in availableConstructors)
                {
                    // check if the constructor is preferred
#if NET35
                    if (constructor.GetCustomAttributes(true).OfType <PreferConstructorAttribute>().Any())
#else // NET35
                    if (constructor.GetCustomAttribute <PreferConstructorAttribute>() != null)
#endif // !NET35
                    {
                        // constructor has the attribute
                        return(constructor);
                    }
                }
            }

            // search complexest constructor
            if (context.ConstructionMode == ServiceConstructionMode.PreferComplexConstructor ||
                context.ConstructionMode == ServiceConstructionMode.Mixed)
            {
                // iterate through all available constructors and find the complexest
                var constructor = availableConstructors
#if SUPPORTS_READONLY_COLLECTIONS
                                  .Select(s => new KeyValuePair <ConstructorInfo, IReadOnlyList <ParameterInfo> >(s, s.GetParameters()))
                                  .OrderByDescending(s => s.Value.Count) // order by parameter count (descending)
#else // SUPPORTS_READONLY_COLLECTIONS
                                  .Select(s => new KeyValuePair <ConstructorInfo, ParameterInfo[]>(s, s.GetParameters()))
                                  .OrderByDescending(s => s.Value.Length) // order by parameter count (descending)
#endif // !SUPPORTS_READONLY_COLLECTIONS
                                  .FirstOrDefault(s => CanUseConstructor(context.Register, s.Value));

                // check if no constructor was found
                if (constructor.Key is null)
                {
                    // throw exception: No constructor was found for the type.
                    throw new ResolverException($"Could not find a passable constructor for '{implementationType}'.", context);
                }

                return(constructor.Key);
            }

            // search parameter-less constructor
            if (context.ConstructionMode == ServiceConstructionMode.PreferParameterlessConstructor)
            {
                // iterate through all available constructors and find a parameter-less
                var constructor = availableConstructors.FirstOrDefault(s => s.GetParameters().Length == 0);

                // check if no constructor was found
                if (constructor is null)
                {
                    // throw exception: No parameter-less constructor
                    throw new ResolverException($"Could not find a parameter-less constructor for '{implementationType}'.", context);
                }

                return(constructor);
            }

            // throw exception: Service Construction mode out of range
            throw new ArgumentOutOfRangeException(nameof(constructionMode), constructionMode,
                                                  $"Invalid or unsupported service construction mode: '{constructionMode}'.");
        }
Exemple #11
0
 /// <summary>
 ///     Creates the instance.
 /// </summary>
 /// <param name="context">the current resolver context</param>
 /// <returns>the instance</returns>
 protected override object CreateService(ServiceResolveContext context) => new TImplementation();