private static IEnumerable <IInstanceCreator> GetFactoryCreators(Type targetType, Type availableType)
        {
            Debug.Assert(targetType != null);
            Debug.Assert(availableType != null);
            Debug.Assert(availableType.IsAbstract && availableType.IsSealed);

            var factoryMethods =
                from m in availableType.GetMethods(BindingFlags.Public | BindingFlags.Static)
                // Check that method is a "GetInstances" factory method, and returns an IEnumerable<> collection.
                where m.Name.StartsWith("Get", StringComparison.OrdinalIgnoreCase) &&
                m.Name.EndsWith("Instances", StringComparison.OrdinalIgnoreCase) &&
                m.ReturnType.IsGenericType &&
                m.ReturnType.GetGenericTypeDefinition( ) == typeof(IEnumerable <>)
                // Check that the enumerable collection is of type Func<>.
                let enumerableArgType = m.ReturnType.GetGenericArguments( )[0]
                                        where enumerableArgType.IsGenericType &&
                                        enumerableArgType.GetGenericTypeDefinition( ) == typeof(Func <>)
                                        // Check that the return type of the Func<> delegate is valid for the target type.
                                        let funcArgType = enumerableArgType.GetGenericArguments( )[0]
                                                          where targetType.Is(funcArgType)
                                                          select m;

            // Call each factory method, returning creators from the resulting Func<> delegates.
            var factoryCreators =
                from method in factoryMethods
                from methodCreator in TypeCreator.GetMethodCreators(method.ReturnType, method)
                let funcCollection = (System.Collections.IEnumerable)methodCreator.CreateInstance( )
                                     from func in funcCollection.Cast <object>( )
                                     let creator = WeakInstanceCreator.ForDelegate(func)
                                                   select creator;

            return(factoryCreators);
        }
        private static IEnumerable <IInstanceCreator> GetMethodCreators(Type targetType, MethodBase method)
        {
            Debug.Assert(targetType != null);
            Debug.Assert(method != null);
            Debug.Assert(method.IsGenericMethod || !targetType.ContainsGenericParameters);

            // Ignore recursive parameters.
            var parameters = method.GetParameters( );

            if (parameters.Any(p => p.ParameterType.Is(targetType) || p.ParameterType.Is(method.DeclaringType)))
            {
                yield break;
            }

            // Retrieve creators for each parameter.
            var availableArguments = parameters.Select((p) => TypeCreator.GetInstanceCreators(p.ParameterType).AsEnumerable( ));

            // Call constructor with all argument permutations.
            foreach (var arguments in Permuter.Permute(availableArguments))
            {
                // If method is concrete, use it.
                if (!method.IsGenericMethod)
                {
                    yield return(WeakInstanceCreator.ForMethod(targetType, method, arguments));
                }
                // Otherwise, try to resolve generic arguments on method.
                else if (method is MethodInfo)
                {
                    var methodInfo = (MethodInfo)method;
                    var bindings   = new BindingCollection(Binding.EmptyBindings);
                    for (int i = 0; i < parameters.Length; ++i)
                    {
                        ParameterInfo    parameter = parameters[i];
                        IInstanceCreator argument  = arguments[i];
                        if (parameter.ParameterType.ContainsGenericParameters)
                        {
                            GenericTypeResolver.GetAssignedGenericArguments(bindings, argument.InstanceType, parameter.ParameterType);
                        }
                    }

                    foreach (LinkList <Binding> b in bindings)
                    {
                        var concreteMethod = GenericTypeResolver.MakeConcreteMethod(methodInfo, b);
                        if (concreteMethod != null)
                        {
                            targetType = concreteMethod.ReturnType;
                            yield return(WeakInstanceCreator.ForMethod(targetType, concreteMethod, arguments));
                        }
                    }
                }
            }
        }
        private static IEnumerable <IInstanceCreator> GetConstructorCreators(Type targetType, Type availableType)
        {
            Debug.Assert(targetType != null);
            Debug.Assert(availableType != null);
            Debug.Assert(!availableType.IsAbstract);

            if (targetType.ContainsGenericParameters)
            {
                Type definition = targetType.IsGenericParameter ? targetType : targetType.GetGenericTypeDefinition( );
                var  bindings   = new BindingCollection(Binding.EmptyBindings);
                GenericTypeResolver.GetAssignedGenericArguments(bindings, availableType, definition);

                foreach (var binding in bindings)
                {
                    Type resolvedType =
                        definition.IsGenericParameter
                            ? Binding.ForArgument(binding, definition).Type
                            : GenericTypeResolver.MakeConcreteType(definition, binding);

                    targetType = resolvedType;
                    break;
                }
            }

            var creators = new List <IInstanceCreator>( );

            // If type is an enumeration, get creator for enum values.
            if (availableType.IsEnum || availableType == typeof(bool))
            {
                creators.AddRange(WeakInstanceCreator.ForEnum(availableType));
            }
            // Otherwise, get creator for any default constructor.
            else if (Constraint.HasDefaultConstructor(availableType))
            {
                creators.Add(WeakInstanceCreator.ForType(availableType));
            }

            // Get creators for any parameterized constructors.
            var parameterizedConstructors = availableType.GetConstructors( ).Where((c) => c.GetParameters( ).Length > 0).ToArray( );

            if (parameterizedConstructors.Length < 3)
            {
                foreach (var constructor in parameterizedConstructors)
                {
                    creators.AddRange(TypeCreator.GetMethodCreators(targetType, constructor));
                }
            }

            return(creators);
        }
        private static ReadOnlyCollection <IInstanceCreator> GetInstanceCreators(Type targetType)
        {
            Debug.Assert(targetType != null);
            Debug.Assert(targetType.IsVisible);

            // If creators have not been cached, or are in the process of being cached, take lock and re-check cache.
            ReadOnlyCollection <IInstanceCreator> cached;

            if (!creatorCache_.TryGetValue(targetType, out cached) || object.ReferenceEquals(cached, TempCreators))
            {
                bool   isInstanceCreator = targetType.IsGenericType && targetType.GetGenericTypeDefinition( ) == typeof(IInstanceCreator <>);
                Type[] availableTypes    = isInstanceCreator ? null : TypeLoader.GetUsableTypes(targetType).ToArray( );
                lock ( creatorCacheLock_ ) {
                    if (!TypeCreator.creatorCache_.ContainsKey(targetType))
                    {
                        TypeCreator.creatorCache_[targetType] = TempCreators;
                        ReadOnlyCollection <IInstanceCreator> creators;

                        // If target type is for IInstanceCreator<T>, wrap creators for T.
                        if (isInstanceCreator)
                        {
                            Type innerTargetType = targetType.GetGenericArguments( )[0];
                            var  innerCreators   = TypeCreator.GetCreators(innerTargetType);

                            var outerCreators = new IInstanceCreator[innerCreators.Count];
                            for (int i = 0; i < outerCreators.Length; ++i)
                            {
                                outerCreators[i] = WeakInstanceCreator.ForInstanceCreator(targetType, innerCreators[i]);
                            }
                            creators = outerCreators.ToReadOnlyCollection( );
                        }
                        // Otherwise, get creators for type directly.
                        else
                        {
                            creators = GetInstanceCreators(targetType, availableTypes);
                        }

                        TypeCreator.creatorCache_[targetType] = creators;
                    }
                }
            }

            return(TypeCreator.creatorCache_[targetType]);
        }
            public static IInstanceCreator ForInstanceCreator(Type targetType, IInstanceCreator creator)
            {
                Debug.Assert(creator != null);
                Debug.Assert(targetType != null);
                Debug.Assert(targetType.IsGenericType && targetType.GetGenericTypeDefinition( ) == typeof(IInstanceCreator <>));

                IInstanceCreator finalCreator      = creator;
                Type             creatorType       = creator.GetType( );
                Type             targetCreatedType = targetType.GetGenericArguments( )[0];

                // Ensure target type is closed.
                Type finalTargetType = targetType;

                if (finalTargetType.ContainsGenericParameters)
                {
                    targetCreatedType = GenericTypeResolver.GetCorrespondingBaseTypes(finalCreator.InstanceType, targetCreatedType).Single( );
                    finalTargetType   = typeof(IInstanceCreator <>).MakeGenericType(targetCreatedType);
                }

                // If the creator does not have the same type as the target, wrap the creator to return instances of the target base type.
                if (!creatorType.Is(finalTargetType))
                {
                    Type actualCreatedType = creatorType.GetInterfaces( )
                                             .Single(i => i.IsGenericType && i.GetGenericTypeDefinition( ) == typeof(IInstanceCreator <>))
                                             .GetGenericArguments( )[0];

                    Type wrapperType = typeof(InstanceCreatorWrapper <,>).MakeGenericType(targetCreatedType, actualCreatedType);
                    finalCreator = (IInstanceCreator)Activator.CreateInstance(wrapperType, creator);
                }

                // Get IInstanceCreator to return the given creator instance.
                Type funcType       = typeof(Func <>).MakeGenericType(finalTargetType);
                var  lambda         = Expression.Lambda(funcType, Expression.Constant(finalCreator, finalTargetType));
                var  nestingCreator = WeakInstanceCreator.ForDelegate(lambda.Compile( ));

                return(nestingCreator);
            }