public void CreateTypeIsOnlyInvokedOnceOnSuccess() { int invocationCount = 0; Func <Type, Type> createTypeDelegate = type => { invocationCount++; return(typeof(MyProxyClass)); }; var cache = new ProxyTypeCache(); for (int i = 0; i < 2; i++) { Assert.AreEqual(typeof(MyProxyClass), cache.GetProxyType(typeof(IMyInterface), createTypeDelegate)); } Assert.AreEqual(1, invocationCount); }
public void CreateTypeIsOnlyInvokedOnceOnFailure() { int invocationCount = 0; var createTypeException = new Exception(); Func <Type, Type> createTypeDelegate = type => { invocationCount++; throw createTypeException; }; var cache = new ProxyTypeCache(); for (var i = 0; i < 2; i++) { var ex = Assert.Throws <InvalidOperationException>(() => cache.GetProxyType(typeof(IMyInterface), createTypeDelegate)); Assert.AreSame(createTypeException, ex.InnerException); } Assert.AreEqual(1, invocationCount); }
public ProxyBuilderContext(ProxyTypeCache cache, Type targetType, Type sourceType) { Cache = cache; Key = new Tuple<Type, Type>(sourceType, targetType); Visited = new Dictionary<Tuple<Type, Type>, VerificationResult>(); }
public static Type GetProxyType(ProxyTypeCache cache, Type targetType, Type sourceType) { if (targetType.IsAssignableFrom(sourceType)) { 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; } }
public void SetUp() { _builder = new ProxyBuilder("ProxyTypeCacheTests", "ProxyTypeCacheTests.dll"); _cache = new ProxyTypeCache(_builder); }