Beispiel #1
0
        public Indexer Close([NotNull] Type[] typeClosures)
        {
            if (typeClosures == null)
            {
                throw new ArgumentNullException("typeClosures");
            }

            // Check input arrays are valid.
            if (typeClosures.Length != ExtendedType.GenericArguments.Count())
            {
                return(null);
            }

            // If we haven't got any type closures, we can return this indexer.
            if (typeClosures.All(t => t == null))
            {
                return(this);
            }

            // Close type
            ExtendedType et = ExtendedType.CloseType(typeClosures);

            // Check closure succeeded.
            if (et == null)
            {
                return(null);
            }

            // Create new search.
            Debug.Assert(_indexParameters.Value != null);
            int pCount = _indexParameters.Value.Length;

            TypeSearch[] searchTypes = new TypeSearch[pCount + 1];

            Type[] typeGenericArguments = et.GenericArguments.Select(g => g.Type).ToArray();

            // Search for closed
            Type[] emptyTypes = Array <Type> .Empty;
            for (int i = 0; i < pCount; i++)
            {
                Debug.Assert(_indexParameters.Value[i] != null);
                Type pType = _indexParameters.Value[i].ParameterType;
                searchTypes[i] = Reflection.ExpandParameterType(pType, emptyTypes, typeGenericArguments);
            }

            // Add return type
            searchTypes[pCount] = Reflection.ExpandParameterType(
                Info.PropertyType,
                emptyTypes,
                typeGenericArguments);

            // Search for indexer on new type.
            return(et.GetIndexer(searchTypes));
        }
        public void ExtendedType_CanGetConcreteMethods()
        {
            // Get the open type.
            ExtendedType openType = ExtendedType.Get(typeof(ComplexOverloads <>));

            Assert.IsTrue(openType.Type.ContainsGenericParameters);

            // Close the type
            ExtendedType closedType = openType.CloseType(typeof(int));

            Assert.IsNotNull(closedType);
            Assert.IsFalse(closedType.Type.ContainsGenericParameters);
            Assert.AreSame(openType.Type, closedType.Type.GetGenericTypeDefinition());

            // This time we have a concrete type.
            Method method = closedType.GetMethod("A", typeof(int));

            Assert.IsNotNull(method);
            // This method has no generic arguments and the type is concrete.
            Assert.IsFalse(method.Info.ContainsGenericParameters);

            Method method2 = closedType.GetMethod("A", 1, typeof(string), TypeSearch.Void);

            Assert.IsNotNull(method2);
            // This method has generic arguments and so it does contain generic parameters even though type is concrete.
            Assert.IsTrue(method2.Info.ContainsGenericParameters);

            // We can use the CloseMethod overload to close the method.
            Method method3 = method2.Close(typeof(int));

            Assert.IsNotNull(method3);
            // We haven't closed the extended type.
            Assert.AreSame(method2.ExtendedType, method3.ExtendedType);
            Assert.IsFalse(method3.ExtendedType.Type.ContainsGenericParameters);
            Assert.IsFalse(method3.Info.ContainsGenericParameters);

            // Finally we get the open type's open method.
            Method method4 = openType.GetMethod("A", 1, typeof(string), TypeSearch.Void);

            Assert.IsNotNull(method4);
            Assert.IsTrue(method4.Info.ContainsGenericParameters);
        }
Beispiel #3
0
        public Method Close([NotNull] Type[] typeClosures, [NotNull] Type[] signatureClosures)
        {
            if (typeClosures == null)
            {
                throw new ArgumentNullException("typeClosures");
            }
            if (signatureClosures == null)
            {
                throw new ArgumentNullException("signatureClosures");
            }

            Debug.Assert(_genericArguments.Value != null);

            // Check input arrays are valid.
            if ((typeClosures.Length != ExtendedType.GenericArguments.Count()) ||
                (signatureClosures.Length != _genericArguments.Value.Count()))
            {
                return(null);
            }

            // If we have any type closures then we need to close the type and look for the method on there.
            if (typeClosures.Any(t => t != null))
            {
                // Close type
                ExtendedType et = ExtendedType.CloseType(typeClosures);

                // Check closure succeeded.
                if (et == null)
                {
                    return(null);
                }

                // Create new search.
                Debug.Assert(_parameters.Value != null);
                int          pCount               = _parameters.Value.Length;
                TypeSearch[] searchTypes          = new TypeSearch[pCount + 1];
                Type[]       typeGenericArguments = et.GenericArguments.Select(g => g.Type).ToArray();
                // Search for closed
                for (int i = 0; i < pCount; i++)
                {
                    Debug.Assert(_parameters.Value[i] != null);
                    Type pType = _parameters.Value[i].ParameterType;
                    Debug.Assert(pType != null);
                    searchTypes[i] = Reflection.ExpandParameterType(pType, signatureClosures, typeGenericArguments);
                }

                // Add return type
                Type rType = Info.ReturnType;
                searchTypes[pCount] = Reflection.ExpandParameterType(rType, signatureClosures, typeGenericArguments);

                // Search for method on new type.
                return(et.GetMethod(Info.Name, signatureClosures.Length, searchTypes));
            }

            // Substitute missing types with concrete ones.
            int closures = signatureClosures.Length;

            Type[] gta = new Type[closures];
            for (int i = 0; i < closures; i++)
            {
                gta[i] = signatureClosures[i] ?? _genericArguments.Value[i].Type;
            }

            // Create closed method, cache it and return.
            // ReSharper disable once AssignNullToNotNullAttribute
            string key = string.Join("|", gta.Select(t => ExtendedType.Get(t).Signature));

            Debug.Assert(_closedMethods.Value != null);
            return(_closedMethods.Value.GetOrAdd(
                       key,
                       k =>
            {
                try
                {
                    return new Method(ExtendedType, Info.MakeGenericMethod(gta));
                }
                catch (ArgumentException)
                {
                    return null;
                }
            }));
        }