Skip to content

Commit b945f88

Browse files
Merge pull request #44092 from dotnet/main
Merge main into live
2 parents b54c6fb + 9c423c0 commit b945f88

File tree

2 files changed

+67
-17
lines changed

2 files changed

+67
-17
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System;
2+
using System.Collections;
3+
using System.Globalization;
24
using System.IO;
35
using System.Reflection;
46
using System.Reflection.Emit;
@@ -13,11 +15,12 @@ public static void Main()
1315
{
1416
SetEntryPoint();
1517
SetResource();
18+
ReadResource();
1619
}
1720
// <Snippet1>
1821
public static void SetEntryPoint()
1922
{
20-
PersistedAssemblyBuilder ab = new PersistedAssemblyBuilder(new AssemblyName("MyAssembly"), typeof(object).Assembly);
23+
PersistedAssemblyBuilder ab = new(new AssemblyName("MyAssembly"), typeof(object).Assembly);
2124
TypeBuilder tb = ab.DefineDynamicModule("MyModule").DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class);
2225
// ...
2326
MethodBuilder entryPoint = tb.DefineMethod("Main", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static);
@@ -27,50 +30,93 @@ public static void SetEntryPoint()
2730
tb.CreateType();
2831

2932
MetadataBuilder metadataBuilder = ab.GenerateMetadata(out BlobBuilder ilStream, out BlobBuilder fieldData);
30-
PEHeaderBuilder peHeaderBuilder = new PEHeaderBuilder(imageCharacteristics: Characteristics.ExecutableImage);
3133

32-
ManagedPEBuilder peBuilder = new ManagedPEBuilder(
33-
header: peHeaderBuilder,
34+
ManagedPEBuilder peBuilder = new(
35+
header: PEHeaderBuilder.CreateExecutableHeader(),
3436
metadataRootBuilder: new MetadataRootBuilder(metadataBuilder),
3537
ilStream: ilStream,
3638
mappedFieldData: fieldData,
3739
entryPoint: MetadataTokens.MethodDefinitionHandle(entryPoint.MetadataToken));
3840

39-
BlobBuilder peBlob = new BlobBuilder();
41+
BlobBuilder peBlob = new();
4042
peBuilder.Serialize(peBlob);
4143

42-
// in case saving to a file:
43-
using var fileStream = new FileStream("MyAssembly.exe", FileMode.Create, FileAccess.Write);
44+
// Create the executable:
45+
using FileStream fileStream = new("MyAssembly.exe", FileMode.Create, FileAccess.Write);
4446
peBlob.WriteContentTo(fileStream);
4547
}
4648
// </Snippet1>
4749
// <Snippet2>
4850
public static void SetResource()
4951
{
50-
PersistedAssemblyBuilder ab = new PersistedAssemblyBuilder(new AssemblyName("MyAssembly"), typeof(object).Assembly);
52+
PersistedAssemblyBuilder ab = new(new AssemblyName("MyAssembly"), typeof(object).Assembly);
5153
ab.DefineDynamicModule("MyModule");
5254
MetadataBuilder metadata = ab.GenerateMetadata(out BlobBuilder ilStream, out _);
5355

54-
using MemoryStream stream = new MemoryStream();
55-
ResourceWriter myResourceWriter = new ResourceWriter(stream);
56+
using MemoryStream stream = new();
57+
ResourceWriter myResourceWriter = new(stream);
5658
myResourceWriter.AddResource("AddResource 1", "First added resource");
5759
myResourceWriter.AddResource("AddResource 2", "Second added resource");
5860
myResourceWriter.AddResource("AddResource 3", "Third added resource");
5961
myResourceWriter.Close();
60-
BlobBuilder resourceBlob = new BlobBuilder();
61-
resourceBlob.WriteBytes(stream.ToArray());
62-
metadata.AddManifestResource(ManifestResourceAttributes.Public, metadata.GetOrAddString("MyResource"), default, (uint)resourceBlob.Count);
6362

64-
ManagedPEBuilder peBuilder = new ManagedPEBuilder(
65-
header: new PEHeaderBuilder(imageCharacteristics: Characteristics.ExecutableImage | Characteristics.Dll),
63+
byte[] data = stream.ToArray();
64+
BlobBuilder resourceBlob = new();
65+
resourceBlob.WriteInt32(data.Length);
66+
resourceBlob.WriteBytes(data);
67+
68+
metadata.AddManifestResource(
69+
ManifestResourceAttributes.Public,
70+
metadata.GetOrAddString("MyResource.resources"),
71+
implementation: default,
72+
offset: 0);
73+
74+
ManagedPEBuilder peBuilder = new(
75+
header: PEHeaderBuilder.CreateLibraryHeader(),
6676
metadataRootBuilder: new MetadataRootBuilder(metadata),
6777
ilStream: ilStream,
6878
managedResources: resourceBlob);
6979

70-
BlobBuilder blob = new BlobBuilder();
80+
BlobBuilder blob = new();
7181
peBuilder.Serialize(blob);
72-
using var fileStream = new FileStream("MyAssemblyWithResource.dll", FileMode.Create, FileAccess.Write);
82+
83+
// Create the assembly:
84+
using FileStream fileStream = new("MyAssemblyWithResource.dll", FileMode.Create, FileAccess.Write);
7385
blob.WriteContentTo(fileStream);
7486
}
7587
// </Snippet2>
88+
// <Snippet3>
89+
public static void ReadResource()
90+
{
91+
Assembly readAssembly = Assembly.LoadFile(Path.Combine(
92+
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
93+
"MyAssemblyWithResource.dll"));
94+
95+
// Use ResourceManager.GetString() to read the resources.
96+
ResourceManager rm = new("MyResource", readAssembly);
97+
Console.WriteLine("Using ResourceManager.GetString():");
98+
Console.WriteLine($"{rm.GetString("AddResource 1", CultureInfo.InvariantCulture)}");
99+
Console.WriteLine($"{rm.GetString("AddResource 2", CultureInfo.InvariantCulture)}");
100+
Console.WriteLine($"{rm.GetString("AddResource 3", CultureInfo.InvariantCulture)}");
101+
102+
// Use ResourceSet to enumerate the resources.
103+
Console.WriteLine();
104+
Console.WriteLine("Using ResourceSet:");
105+
ResourceSet resourceSet = rm.GetResourceSet(CultureInfo.InvariantCulture, createIfNotExists: true, tryParents: false);
106+
foreach (DictionaryEntry entry in resourceSet)
107+
{
108+
Console.WriteLine($"Key: {entry.Key}, Value: {entry.Value}");
109+
}
110+
111+
// Use ResourceReader to enumerate the resources.
112+
Console.WriteLine();
113+
Console.WriteLine("Using ResourceReader:");
114+
using Stream stream = readAssembly.GetManifestResourceStream("MyResource.resources")!;
115+
using ResourceReader reader = new(stream);
116+
foreach (DictionaryEntry entry in reader)
117+
{
118+
Console.WriteLine($"Key: {entry.Key}, Value: {entry.Value}");
119+
}
120+
}
121+
// </Snippet3>
76122
}

docs/fundamentals/runtime-libraries/system-reflection-emit-persistedassemblybuilder.md

+4
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ The following example shows how to create resources and attach it to the assembl
120120

121121
:::code language="csharp" source="./snippets/System.Reflection.Emit/PersistedAssemblyBuilder/Overview/csharp/GenerateMetadataSnippets.cs" id="Snippet2":::
122122

123+
The following example shows how to read resources from the created assembly.
124+
125+
:::code language="csharp" source="./snippets/System.Reflection.Emit/PersistedAssemblyBuilder/Overview/csharp/GenerateMetadataSnippets.cs" id="Snippet3":::
126+
123127
> [!NOTE]
124128
> The metadata tokens for all members are populated on the <xref:System.Reflection.Emit.AssemblyBuilder.Save%2A> 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.
125129
>

0 commit comments

Comments
 (0)