diff --git a/docs/fundamentals/runtime-libraries/snippets/System.Reflection.Emit/PersistedAssemblyBuilder/Overview/csharp/GenerateMetadataSnippets.cs b/docs/fundamentals/runtime-libraries/snippets/System.Reflection.Emit/PersistedAssemblyBuilder/Overview/csharp/GenerateMetadataSnippets.cs index a637dc97266f6..1b21cd5427287 100644 --- a/docs/fundamentals/runtime-libraries/snippets/System.Reflection.Emit/PersistedAssemblyBuilder/Overview/csharp/GenerateMetadataSnippets.cs +++ b/docs/fundamentals/runtime-libraries/snippets/System.Reflection.Emit/PersistedAssemblyBuilder/Overview/csharp/GenerateMetadataSnippets.cs @@ -1,4 +1,6 @@ using System; +using System.Collections; +using System.Globalization; using System.IO; using System.Reflection; using System.Reflection.Emit; @@ -13,11 +15,12 @@ public static void Main() { SetEntryPoint(); SetResource(); + ReadResource(); } // public static void SetEntryPoint() { - PersistedAssemblyBuilder ab = new PersistedAssemblyBuilder(new AssemblyName("MyAssembly"), typeof(object).Assembly); + PersistedAssemblyBuilder ab = new(new AssemblyName("MyAssembly"), typeof(object).Assembly); TypeBuilder tb = ab.DefineDynamicModule("MyModule").DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class); // ... MethodBuilder entryPoint = tb.DefineMethod("Main", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static); @@ -27,50 +30,93 @@ public static void SetEntryPoint() tb.CreateType(); MetadataBuilder metadataBuilder = ab.GenerateMetadata(out BlobBuilder ilStream, out BlobBuilder fieldData); - PEHeaderBuilder peHeaderBuilder = new PEHeaderBuilder(imageCharacteristics: Characteristics.ExecutableImage); - ManagedPEBuilder peBuilder = new ManagedPEBuilder( - header: peHeaderBuilder, + ManagedPEBuilder peBuilder = new( + header: PEHeaderBuilder.CreateExecutableHeader(), metadataRootBuilder: new MetadataRootBuilder(metadataBuilder), ilStream: ilStream, mappedFieldData: fieldData, entryPoint: MetadataTokens.MethodDefinitionHandle(entryPoint.MetadataToken)); - BlobBuilder peBlob = new BlobBuilder(); + BlobBuilder peBlob = new(); peBuilder.Serialize(peBlob); - // in case saving to a file: - using var fileStream = new FileStream("MyAssembly.exe", FileMode.Create, FileAccess.Write); + // Create the executable: + using FileStream fileStream = new("MyAssembly.exe", FileMode.Create, FileAccess.Write); peBlob.WriteContentTo(fileStream); } // // public static void SetResource() { - PersistedAssemblyBuilder ab = new PersistedAssemblyBuilder(new AssemblyName("MyAssembly"), typeof(object).Assembly); + PersistedAssemblyBuilder ab = new(new AssemblyName("MyAssembly"), typeof(object).Assembly); ab.DefineDynamicModule("MyModule"); MetadataBuilder metadata = ab.GenerateMetadata(out BlobBuilder ilStream, out _); - using MemoryStream stream = new MemoryStream(); - ResourceWriter myResourceWriter = new ResourceWriter(stream); + using MemoryStream stream = new(); + ResourceWriter myResourceWriter = new(stream); myResourceWriter.AddResource("AddResource 1", "First added resource"); myResourceWriter.AddResource("AddResource 2", "Second added resource"); myResourceWriter.AddResource("AddResource 3", "Third added resource"); myResourceWriter.Close(); - BlobBuilder resourceBlob = new BlobBuilder(); - resourceBlob.WriteBytes(stream.ToArray()); - metadata.AddManifestResource(ManifestResourceAttributes.Public, metadata.GetOrAddString("MyResource"), default, (uint)resourceBlob.Count); - ManagedPEBuilder peBuilder = new ManagedPEBuilder( - header: new PEHeaderBuilder(imageCharacteristics: Characteristics.ExecutableImage | Characteristics.Dll), + byte[] data = stream.ToArray(); + BlobBuilder resourceBlob = new(); + resourceBlob.WriteInt32(data.Length); + resourceBlob.WriteBytes(data); + + metadata.AddManifestResource( + ManifestResourceAttributes.Public, + metadata.GetOrAddString("MyResource.resources"), + implementation: default, + offset: 0); + + ManagedPEBuilder peBuilder = new( + header: PEHeaderBuilder.CreateLibraryHeader(), metadataRootBuilder: new MetadataRootBuilder(metadata), ilStream: ilStream, managedResources: resourceBlob); - BlobBuilder blob = new BlobBuilder(); + BlobBuilder blob = new(); peBuilder.Serialize(blob); - using var fileStream = new FileStream("MyAssemblyWithResource.dll", FileMode.Create, FileAccess.Write); + + // Create the assembly: + using FileStream fileStream = new("MyAssemblyWithResource.dll", FileMode.Create, FileAccess.Write); blob.WriteContentTo(fileStream); } // + // + public static void ReadResource() + { + Assembly readAssembly = Assembly.LoadFile(Path.Combine( + Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), + "MyAssemblyWithResource.dll")); + + // Use ResourceManager.GetString() to read the resources. + ResourceManager rm = new("MyResource", readAssembly); + Console.WriteLine("Using ResourceManager.GetString():"); + Console.WriteLine($"{rm.GetString("AddResource 1", CultureInfo.InvariantCulture)}"); + Console.WriteLine($"{rm.GetString("AddResource 2", CultureInfo.InvariantCulture)}"); + Console.WriteLine($"{rm.GetString("AddResource 3", CultureInfo.InvariantCulture)}"); + + // Use ResourceSet to enumerate the resources. + Console.WriteLine(); + Console.WriteLine("Using ResourceSet:"); + ResourceSet resourceSet = rm.GetResourceSet(CultureInfo.InvariantCulture, createIfNotExists: true, tryParents: false); + foreach (DictionaryEntry entry in resourceSet) + { + Console.WriteLine($"Key: {entry.Key}, Value: {entry.Value}"); + } + + // Use ResourceReader to enumerate the resources. + Console.WriteLine(); + Console.WriteLine("Using ResourceReader:"); + using Stream stream = readAssembly.GetManifestResourceStream("MyResource.resources")!; + using ResourceReader reader = new(stream); + foreach (DictionaryEntry entry in reader) + { + Console.WriteLine($"Key: {entry.Key}, Value: {entry.Value}"); + } + } + // } diff --git a/docs/fundamentals/runtime-libraries/system-reflection-emit-persistedassemblybuilder.md b/docs/fundamentals/runtime-libraries/system-reflection-emit-persistedassemblybuilder.md index 8cc56fecdbaba..2c2a4fb57a63a 100644 --- a/docs/fundamentals/runtime-libraries/system-reflection-emit-persistedassemblybuilder.md +++ b/docs/fundamentals/runtime-libraries/system-reflection-emit-persistedassemblybuilder.md @@ -120,6 +120,10 @@ The following example shows how to create resources and attach it to the assembl :::code language="csharp" source="./snippets/System.Reflection.Emit/PersistedAssemblyBuilder/Overview/csharp/GenerateMetadataSnippets.cs" id="Snippet2"::: +The following example shows how to read resources from the created assembly. + +:::code language="csharp" source="./snippets/System.Reflection.Emit/PersistedAssemblyBuilder/Overview/csharp/GenerateMetadataSnippets.cs" id="Snippet3"::: + > [!NOTE] > The metadata tokens for all members are populated on the operation. Don't use the tokens of a generated type and its members before saving, as they'll have default values or throw exceptions. It's safe to use tokens for types that are referenced, not generated. >