Example #1
0
        /// <summary>
        /// Extracts generic type arguments from a constructed type that are necessary to close a generic type definition.
        /// </summary>
        /// <param name="genericTypeDefinition">A generic type definition.</param>
        /// <param name="constructedType">A closed type from which may be obtained generic type arguments.</param>
        /// <returns>The type argument necessary to construct the closed type.</returns>
        internal static Rental <Type[]> ExtractGenericTypeArguments(Type genericTypeDefinition, Type constructedType)
        {
            Requires.NotNull(genericTypeDefinition, nameof(genericTypeDefinition));
            Requires.NotNull(constructedType, nameof(constructedType));

            var genericTypeDefinitionInfo = genericTypeDefinition.GetTypeInfo();

            // The generic type arguments may be buried in the base type of the "constructedType" that we were given.
            var constructedGenericType = constructedType;

            while (constructedGenericType != null && (!constructedGenericType.GetTypeInfo().IsGenericType || !genericTypeDefinitionInfo.IsAssignableFrom(constructedGenericType.GetGenericTypeDefinition().GetTypeInfo())))
            {
                constructedGenericType = constructedGenericType.GetTypeInfo().BaseType;
            }

            Requires.Argument(constructedGenericType != null, "constructedType", Strings.NotClosedFormOfOther);

            var result = ArrayRental <Type> .Get(genericTypeDefinitionInfo.GenericTypeParameters.Length);

            for (int i = 0; i < result.Value.Length; i++)
            {
                result.Value[i] = constructedGenericType.GenericTypeArguments[i];
            }

            return(result);
        }
Example #2
0
 /// <summary>
 /// Creates a <see cref="Func{T}"/> delegate for a given <see cref="Func{Object}"/> delegate.
 /// </summary>
 /// <param name="func">The function that produces the T value typed as <see cref="object"/>.</param>
 /// <param name="typeArg">The <c>T</c> type argument for the returned function's return type.</param>
 /// <returns>An instance of <see cref="Func{T}"/>, typed as <see cref="Func{Object}"/>.</returns>
 internal static Func <object> As(this Func <object> func, Type typeArg)
 {
     using (var args = ArrayRental <object> .Get(1))
     {
         args.Value[0] = func;
         return((Func <object>)CastAsFuncMethodInfo.MakeGenericMethod(typeArg).Invoke(null, args.Value) !);
     }
 }
Example #3
0
        internal static ICollection <object> GetCollectionWrapper(Type itemType, object collectionObject)
        {
            Requires.NotNull(itemType, nameof(itemType));
            Requires.NotNull(collectionObject, nameof(collectionObject));

            var underlyingItemType = itemType.GetTypeInfo().UnderlyingSystemType;

            if (underlyingItemType == typeof(object))
            {
                return((ICollection <object>)collectionObject);
            }

            // Most common .Net collections implement IList as well so for those
            // cases we can optimize the wrapping instead of using reflection to create
            // a generic type.
            if (typeof(IList).GetTypeInfo().IsAssignableFrom(collectionObject.GetType().GetTypeInfo()))
            {
                return(new CollectionOfObjectList((IList)collectionObject));
            }

            Func <object, ICollection <object> > factory;

            lock (CachedCollectionWrapperFactories)
            {
                CachedCollectionWrapperFactories.TryGetValue(underlyingItemType, out factory);
            }

            if (factory == null)
            {
                Type collectionType = typeof(CollectionOfObject <>).MakeGenericType(underlyingItemType);
#if RuntimeHandles
                var ctor = (ConstructorInfo)MethodBase.GetMethodFromHandle(CollectionOfObjectCtor.MethodHandle, collectionType.TypeHandle);
#else
                var ctor = typeof(CollectionOfObject <>).MakeGenericType(collectionType).GetConstructor(CollectionOfObjectCtorArgTypes);
#endif

                factory = collection =>
                {
                    using (var args = ArrayRental <object> .Get(1))
                    {
                        args.Value[0] = collection;
                        return((ICollection <object>)ctor.Invoke(args.Value));
                    }
                };

                lock (CachedCollectionWrapperFactories)
                {
                    CachedCollectionWrapperFactories[underlyingItemType] = factory;
                }
            }

            return(factory(collectionObject));
        }
            private ValueForImportSite GetValueForImportSite(RuntimePartLifecycleTracker importingPartTracker, RuntimeComposition.RuntimeImport import)
            {
                Requires.NotNull(import, nameof(import));

                Func <Func <object?>, object, object>?lazyFactory = import.LazyFactory;
                var exports = import.SatisfyingExports;

                if (import.Cardinality == ImportCardinality.ZeroOrMore)
                {
                    if (import.ImportingSiteType.IsArray || (import.ImportingSiteType.GetTypeInfo().IsGenericType&& import.ImportingSiteType.GetGenericTypeDefinition().IsEquivalentTo(typeof(IEnumerable <>))))
                    {
                        Array array = Array.CreateInstance(import.ImportingSiteTypeWithoutCollection, exports.Count);
                        using (var intArray = ArrayRental <int> .Get(1))
                        {
                            int i = 0;
                            foreach (var export in exports)
                            {
                                intArray.Value[0] = i++;
                                var exportedValue = this.GetValueForImportElement(importingPartTracker, import, export, lazyFactory);
                                this.ThrowIfExportedValueIsNotAssignableToImport(import, export, exportedValue);
                                array.SetValue(exportedValue, intArray.Value);
                            }
                        }

                        return(new ValueForImportSite(array));
                    }
                    else
                    {
                        object?    collectionObject = null;
                        MemberInfo?importingMember  = import.ImportingMember;
                        if (importingMember != null)
                        {
                            Assumes.NotNull(importingPartTracker.Value);
                            collectionObject = GetImportingMember(importingPartTracker.Value, importingMember);
                        }

                        bool preexistingInstance = collectionObject != null;
                        if (!preexistingInstance)
                        {
                            if (PartDiscovery.IsImportManyCollectionTypeCreateable(import.ImportingSiteType, import.ImportingSiteTypeWithoutCollection))
                            {
                                using (var typeArgs = ArrayRental <Type> .Get(1))
                                {
                                    typeArgs.Value[0] = import.ImportingSiteTypeWithoutCollection;
                                    Type listType = typeof(List <>).MakeGenericType(typeArgs.Value);
                                    if (import.ImportingSiteType.GetTypeInfo().IsAssignableFrom(listType.GetTypeInfo()))
                                    {
                                        collectionObject = Activator.CreateInstance(listType) !;
                                    }
                                    else
                                    {
                                        collectionObject = Activator.CreateInstance(import.ImportingSiteType) !;
                                    }
                                }

                                Assumes.NotNull(importingPartTracker.Value);
                                Assumes.NotNull(importingMember);
                                SetImportingMember(importingPartTracker.Value, importingMember, collectionObject);
                            }
                            else
                            {
                                throw new CompositionFailedException(
                                          string.Format(
                                              CultureInfo.CurrentCulture,
                                              Strings.UnableToInstantiateCustomImportCollectionType,
                                              import.ImportingSiteType.FullName,
                                              $"{import.DeclaringTypeRef.FullName}.{import.ImportingMemberRef?.Name}"));
                            }
                        }

                        var collectionAccessor = CollectionServices.GetCollectionWrapper(import.ImportingSiteTypeWithoutCollection, collectionObject !);
                        if (preexistingInstance)
                        {
                            collectionAccessor.Clear();
                        }

                        foreach (var export in exports)
                        {
                            var exportedValue = this.GetValueForImportElement(importingPartTracker, import, export, lazyFactory);
                            this.ThrowIfExportedValueIsNotAssignableToImport(import, export, exportedValue);
                            collectionAccessor.Add(exportedValue);
                        }

                        return(default(ValueForImportSite)); // signal caller should not set value again.
                    }
                }
                else
                {
                    var export = exports.FirstOrDefault();
                    if (export == null)
                    {
                        return(new ValueForImportSite(null));
                    }

                    var exportedValue = this.GetValueForImportElement(importingPartTracker, import, export, lazyFactory);
                    this.ThrowIfExportedValueIsNotAssignableToImport(import, export, exportedValue);
                    return(new ValueForImportSite(exportedValue));
                }
            }