public void GetProxyType_IfAlreadyInCache_AlsoAddedToVisited_FromType() { // Arrange var targetType = typeof(IPerson); var sourceType = typeof(Person); var key = new Tuple <Type, Type>(sourceType, targetType); var cache = new ProxyTypeCache(); cache[key] = ProxyTypeCacheResult.FromType(key, sourceType, sourceType.GetConstructor(Array.Empty <Type>())); var context = new ProxyTypeEmitter.ProxyBuilderContext(cache, targetType, sourceType); // Act var result = ProxyTypeEmitter.VerifyProxySupport(context, key); var result2 = ProxyTypeEmitter.VerifyProxySupport(context, key); // Assert Assert.True(result); Assert.True(result2); Assert.Single(context.Visited); Assert.Equal(key, context.Visited.Single().Key); }
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 InvalidOperationException(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[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 convertion return(null); } else { return(result.Type); } }