public ProxyBuilderContext(ProxyTypeCache cache, Type targetType, Type sourceType) { Cache = cache; Key = new Tuple <Type, Type>(sourceType, targetType); Visited = new Dictionary <Tuple <Type, Type>, VerificationResult>(); }
private U Convert <T, U>(object value) { var cache = new ProxyTypeCache(); var proxyType = ProxyTypeEmitter.GetProxyType(cache, typeof(U), typeof(T)); Assert.NotNull(proxyType); var proxy = Activator.CreateInstance(proxyType, value); return(Assert.IsAssignableFrom <U>(proxy)); }
private object ConvertTo(object value, Type type) { var cache = new ProxyTypeCache(); var proxyType = ProxyTypeEmitter.GetProxyType(cache, type, value.GetType()); Assert.NotNull(proxyType); var proxy = Activator.CreateInstance(proxyType, value); Assert.IsAssignableFrom(type, proxy); return(proxy); }
public void GetProxyType_Assignable(Type sourceType, Type targetType) { // Arrange var cache = new ProxyTypeCache(); // Act var result = ProxyTypeEmitter.GetProxyType(cache, targetType, sourceType); // Assert Assert.Null(result); }
public void GetProxyType_Identity(Type type) { // Arrange var cache = new ProxyTypeCache(); // Act var result = ProxyTypeEmitter.GetProxyType(cache, type, type); // Assert Assert.Null(result); }
public void GetProxyType_IfAlreadyInCache_AlsoAddedToVisited_FromError() { // Arrange var targetType = typeof(IPerson); var sourceType = typeof(Person); var key = new Tuple <Type, Type>(sourceType, targetType); var cache = new ProxyTypeCache(); cache[key] = ProxyTypeCacheResult.FromError(key, "Test Error"); var context = new ProxyTypeEmitter.ProxyBuilderContext(cache, targetType, sourceType); // Act var result = ProxyTypeEmitter.VerifyProxySupport(context, key); // Assert Assert.False(result); Assert.Equal(key, context.Visited.Single().Key); }
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); } }