public static void CoreAssemblyCanBeAFacade() { Assembly actualCoreAssembly = null; Assembly testAssembly = null; var resolver = new FuncMetadataAssemblyResolver( delegate(MetadataLoadContext context, AssemblyName refName) { if (refName.Name.Equals("mscorlib", StringComparison.OrdinalIgnoreCase)) { return(actualCoreAssembly = context.LoadFromStream(TestUtils.CreateStreamForCoreAssembly())); } //else if (refName.Equals(new AssemblyName(TestData.s_PhonyCoreAssemblyName))) else if (refName.Name == new AssemblyName(TestData.s_PhonyCoreAssemblyName).Name) { return(testAssembly = context.LoadFromByteArray(TestData.s_PhonyCoreAssemblyImage)); } return(null); }); using (MetadataLoadContext lc = new MetadataLoadContext(resolver, coreAssemblyName: TestData.s_PhonyCoreAssemblyName)) { // This is a sanity check to ensure that "TestData.s_PhonyCoreAssemblyName" is actually the def-name of this // assembly. It better be since we told our MetadataLoadContext to use it as our core assembly. Assembly aAgain = lc.LoadFromAssemblyName(TestData.s_PhonyCoreAssemblyName); Type derived = testAssembly.GetType("Derived", throwOnError: true, ignoreCase: false); // Calling BaseType causes the MetadataLoadContext to parse the typespec "Base<object>". Since "object" is a primitive // type, it should be encoded using the short-form "ELEMENT_TYPE_OBJECT." Hence, the MetadataLoadContext is forced // to look up "System.Object" in the core assembly we assigned to it, which in this case is "PhonyCoreAssembly" // which type-forwards System.Object to "mscorlib". Type baseType = derived.BaseType; Assert.NotNull(actualCoreAssembly); // Ensure our resolve handler actually ran. Assert.NotEqual(testAssembly, actualCoreAssembly); Assert.True(baseType.IsConstructedGenericType); Type retrievedObjectType = baseType.GenericTypeArguments[0]; Assert.Equal("System.Object", retrievedObjectType.FullName); Assert.Equal(actualCoreAssembly, retrievedObjectType.Assembly); } }
public static void ResolverFromReferencedAssembliesUsingFullPublicKeyReference() { // Ecma-335 allows an assembly reference to specify a full public key rather than the token. Ensure that those references // still hand out usable AssemblyNames to resolve handlers. AssemblyName assemblyNameReceivedByHandler = null; var resolver = new FuncMetadataAssemblyResolver( delegate(MetadataLoadContext context, AssemblyName name) { if (name.Name == "RedirectCore") { return(context.LoadFromByteArray(TestData.s_SimpleNameOnlyImage)); } assemblyNameReceivedByHandler = name; return(null); }); using (MetadataLoadContext lc = new MetadataLoadContext(resolver, "RedirectCore")) { Assembly a = lc.LoadFromByteArray(TestData.s_AssemblyRefUsingFullPublicKeyImage); Type t = a.GetType("C", throwOnError: true); // We expect this next to call to throw since it asks the MetadataLoadContext to resolve [mscorlib]System.Object and our // resolve handler doesn't return anything for that. Assert.Throws <FileNotFoundException> (() => t.BaseType); // But it did get called with a request to resolve "mscorlib" and we got the correct PKT calculated from the PK. // Note that the original PK is not made available (which follows prior precedent with these apis.) It's not like // anyone binds with the full PK... Assert.NotNull(assemblyNameReceivedByHandler); byte[] expectedPkt = "b77a5c561934e089".HexToByteArray(); byte[] actualPkt = assemblyNameReceivedByHandler.GetPublicKeyToken(); Assert.Equal <byte>(expectedPkt, actualPkt); } }
public static void GetAssemblies_SnapshotIsAtomic() { Assembly a1 = null; var resolver = new FuncMetadataAssemblyResolver( delegate(MetadataLoadContext context, AssemblyName refName) { if (a1 == null) { // Initial request to load core assembly return(a1 = context.LoadFromByteArray(TestData.s_SimpleAssemblyImage)); } return(null); }); using (MetadataLoadContext lc = new MetadataLoadContext(resolver)) { IEnumerable <Assembly> loadedAssembliesSnapshot = lc.GetAssemblies(); Assembly a2 = lc.LoadFromByteArray(TestData.s_SimpleNameOnlyImage); Assembly[] loadedAssemblies = loadedAssembliesSnapshot.ToArray(); Assert.Equal(1, loadedAssemblies.Length); Assert.Equal(a1, loadedAssemblies[0]); } }
public static void ResolverNoUnnecessaryCalls() { int resolveHandlerCallCount = 0; Assembly resolveEventHandlerResult = null; var resolver = new FuncMetadataAssemblyResolver( delegate(MetadataLoadContext context, AssemblyName name) { if (name.Name == "Foo") { resolveHandlerCallCount++; resolveEventHandlerResult = context.LoadFromByteArray(TestData.s_BaseClassesImage); return(resolveEventHandlerResult); } if (name.Name == "mscorlib") { return(context.LoadFromByteArray(TestData.s_SimpleNameOnlyImage)); } return(null); }); // In a single-threaded scenario at least, MetadataLoadContexts shouldn't ask the resolver to bind the same name twice. using (MetadataLoadContext lc = new MetadataLoadContext(resolver)) { Assembly derived = lc.LoadFromByteArray(TestData.s_DerivedClassWithVariationsOnFooImage); Type t1 = derived.GetType("Derived1", throwOnError: true); Type bt1 = t1.BaseType; Type t2 = derived.GetType("Derived2", throwOnError: true); Type bt2 = t2.BaseType; Assert.Equal(1, resolveHandlerCallCount); Assert.Equal(resolveEventHandlerResult, bt1.Assembly); Assert.Equal(resolveEventHandlerResult, bt2.Assembly); } }