Esempio n. 1
0
        public static Type GetProxyType(ProxyTypeCache cache, Type targetType, Type sourceType)
        {
            if (targetType.GetTypeInfo().IsAssignableFrom(sourceType.GetTypeInfo()))
            {
                return(null);
            }

            var key = new Tuple <Type, Type>(sourceType, targetType);

            ProxyTypeCacheResult result;

            if (!cache.TryGetValue(key, out result))
            {
                var context = new ProxyBuilderContext(cache, targetType, sourceType);

                // Check that all required types are proxy-able - this will create the TypeBuilder, Constructor,
                // and property mappings.
                //
                // We need to create the TypeBuilder and Constructor up front to deal with cycles that can occur
                // when generating the proxy properties.
                if (!VerifyProxySupport(context, context.Key))
                {
                    var error = cache[key];
                    Debug.Assert(error != null && error.IsError);
                    throw new InvalidProxyOperationException(error.Error);
                }

                Debug.Assert(context.Visited.ContainsKey(context.Key));

                // Now that we've generated all of the constructors for the proxies, we can generate the properties.
                foreach (var verificationResult in context.Visited)
                {
                    if (verificationResult.Value.Mappings != null)
                    {
                        AddProperties(
                            context,
                            verificationResult.Value.TypeBuilder,
                            verificationResult.Value.Mappings);
                    }
                }

                // Now generate the type
                foreach (var verificationResult in context.Visited)
                {
                    if (verificationResult.Value.TypeBuilder != null)
                    {
                        verificationResult.Value.Type = verificationResult.Value.TypeBuilder.CreateTypeInfo().AsType();
                    }
                }

                // We only want to publish the results after all of the proxies are totally generated.
                foreach (var verificationResult in context.Visited)
                {
                    cache.TryAdd(verificationResult.Key, ProxyTypeCacheResult.FromType(
                                     verificationResult.Key,
                                     verificationResult.Value.Type,
                                     verificationResult.Value.Constructor));
                }

                return(context.Visited[context.Key].Type);
            }
            else if (result.IsError)
            {
                throw new InvalidOperationException(result.Error);
            }
            else if (result.Type == null)
            {
                // This is an identity conversion
                return(null);
            }
            else
            {
                return(result.Type);
            }
        }