Ejemplo n.º 1
0
        /// <summary>
        /// Returns a collection of <see cref="Type"/>s that could potentially be used
        /// to create instances of the <paramref name="referenceType"/>.
        /// </summary>
        public static IEnumerable <Type> GetUsableTypes(Type referenceType)
        {
            Debug.Assert(referenceType != null);

            Assembly[] referenceAssemblies =
                referenceType.IsGenericParameter
                    ? referenceType.GetGenericParameterConstraints( ).Select(c => c.Assembly).Distinct( ).ToArray( )
                    : new[] { referenceType.Assembly };
            return(TypeLoader.GetUsableTypes(referenceAssemblies));
        }
Ejemplo n.º 2
0
        public void GetUsableTypes_uses_assemblies_referenced_by_type_argument( )
        {
            Type referenceType     = typeof(GenericClass <>).GetGenericArguments( ).Single( );
            var  referenceAssembly = referenceType.Assembly;

            var usableTypes         = TypeLoader.GetUsableTypes(referenceType);
            var inReferenceAssembly = usableTypes.Where(t => t.Assembly == referenceAssembly);
            var inOtherAssembly     = usableTypes.Where(t => t.Assembly != referenceAssembly);

            Assert.NotEmpty(inReferenceAssembly);
            Assert.NotEmpty(inOtherAssembly);
        }
Ejemplo n.º 3
0
        public void GetUsableTypes_only_returns_types_from_reference_type_assemblies( )
        {
            Type referenceType     = typeof(TestTypeLoader);
            var  referenceAssembly = referenceType.Assembly;

            var usableTypes = TypeLoader.GetUsableTypes(referenceType);

            Assert.NotEmpty(usableTypes);
            foreach (var type in usableTypes)
            {
                Assert.Equal(referenceAssembly, type.Assembly);
            }
        }
        private static void BindGenericArguments(BindingCollection bindings, LinkList <Type> openArguments)
        {
            Debug.Assert(bindings != null);
            Debug.Assert(openArguments != null);

            foreach (Type argument in openArguments)
            {
                // Get all types satisfying the current constraint.
                Assembly[] referenceAssemblies;
                var        constraints = Constraint.GetConstraints(argument, out referenceAssemblies);

                // If the argument has no limiting constraints, skip it.
                if (constraints.IsEmpty || referenceAssemblies.Length == 0)
                {
                    continue;
                }


                // Add each type satisfying the current generic argument to the list of bindings.
                bool onlyUsageConstraints = constraints.All((c) => c.IsUsageConstraint);
                bindings.Expand(TypeLoader.GetUsableTypes(referenceAssemblies), (constraintBindings, type) => {
                    LinkList <Type> openTypeArguments = GetOpenGenericArguments(type);
                    Constraint.SatisfyConstraints(constraintBindings, type, constraints);
                    constraintBindings.Reduce(constraintBinding => {
                        Type concreteType = MakeConcreteType(type, openTypeArguments, constraintBinding);
                        if (concreteType == null)
                        {
                            return(null);
                        }
                        else if (onlyUsageConstraints || Binding.ContainsArgument(constraintBinding, argument))
                        {
                            return(constraintBinding);
                        }
                        else
                        {
                            return(constraintBinding.Add(new Binding(argument, concreteType)));
                        }
                    });
                });

                if (bindings.Count == 0)
                {
                    break;
                }
            }
        }
        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]);
        }