ModuleBuilder.DefineManifestResource 方法
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
定义表示要在动态程序集中嵌入的清单资源的二进制大对象 (BLOB)。
public:
void DefineManifestResource(System::String ^ name, System::IO::Stream ^ stream, System::Reflection::ResourceAttributes attribute);
public void DefineManifestResource (string name, System.IO.Stream stream, System.Reflection.ResourceAttributes attribute);
member this.DefineManifestResource : string * System.IO.Stream * System.Reflection.ResourceAttributes -> unit
Public Sub DefineManifestResource (name As String, stream As Stream, attribute As ResourceAttributes)
参数
- name
- String
资源的区分大小写的名称。
- stream
- Stream
包含资源字节的流。
- attribute
- ResourceAttributes
一个枚举值,用于指定资源是公共资源还是私有资源。
例外
name
是一个长度为零的字符串。
包含当前模块的动态程序集是瞬态的;也就是说,调用 DefineDynamicModule(String, String) 时没有指定任何文件名。
示例
以下示例生成并保存名为 EmittedManifestResourceAssembly.exe
的动态程序集,其中包含嵌入的非托管资源。 该示例创建由一个模块组成的程序集,并打开一个内存流以包含非托管资源。 然后,代码调用 DefineManifestResource 方法来定义资源。
注意
可以为资源使用任何类型的流;例如,可以从文件读取非托管二进制数据。
该示例使用 Main
方法定义动态模块中的类型,并为方法正文生成 MSIL。 生成方法的 Main
正文并创建类型后,代码示例会将五个字节写入与清单资源关联的流。 保存程序集后,资源将追加到其中。
运行示例后,可以运行发出的程序集。 发出程序集的 Main
方法中的代码读取嵌入的清单资源,并将字节值打印到控制台。 可以使用 Ildasm.exe (IL 反汇编程序) 查看程序集清单中的信息。
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.IO;
public class Example
{
public static void Main()
{
// Define a dynamic assembly with one module. The module
// name and the assembly name are the same.
AssemblyName asmName =
new AssemblyName("EmittedManifestResourceAssembly");
AssemblyBuilder asmBuilder =
AppDomain.CurrentDomain.DefineDynamicAssembly(
asmName,
AssemblyBuilderAccess.RunAndSave
);
ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule(
asmName.Name,
asmName.Name + ".exe"
);
// Create a memory stream for the unmanaged resource data.
// You can use any stream; for example, you might read the
// unmanaged resource data from a binary file. It is not
// necessary to put any data into the stream right now.
MemoryStream ms = new MemoryStream(1024);
// Define a public manifest resource with the name
// "MyBinaryData, and associate it with the memory stream.
modBuilder.DefineManifestResource(
"MyBinaryData",
ms,
ResourceAttributes.Public
);
// Create a type with a public static Main method that will
// be the entry point for the emitted assembly.
//
// The purpose of the Main method in this example is to read
// the manifest resource and display it, byte by byte.
//
TypeBuilder tb = modBuilder.DefineType("Example");
MethodBuilder main = tb.DefineMethod("Main",
MethodAttributes.Public | MethodAttributes.Static
);
// The Main method uses the Assembly type and the Stream
// type.
Type asm = typeof(Assembly);
Type str = typeof(Stream);
// Get MethodInfo objects for the methods called by
// Main.
MethodInfo getEx = asm.GetMethod("GetExecutingAssembly");
// Use the overload of GetManifestResourceStream that
// takes one argument, a string.
MethodInfo getMRS = asm.GetMethod(
"GetManifestResourceStream",
new Type[] {typeof(string)}
);
MethodInfo rByte = str.GetMethod("ReadByte");
// Use the overload of WriteLine that writes an Int32.
MethodInfo write = typeof(Console).GetMethod(
"WriteLine",
new Type[] {typeof(int)}
);
ILGenerator ilg = main.GetILGenerator();
// Main uses two local variables: the instance of the
// stream returned by GetManifestResourceStream, and
// the value returned by ReadByte. The load and store
// instructions refer to these locals by position
// (0 and 1).
LocalBuilder s = ilg.DeclareLocal(str);
LocalBuilder b = ilg.DeclareLocal(typeof(int));
// Call the static Assembly.GetExecutingAssembly() method,
// which leaves the assembly instance on the stack. Push the
// string name of the resource on the stack, and call the
// GetManifestResourceStream(string) method of the assembly
// instance.
ilg.EmitCall(OpCodes.Call, getEx, null);
ilg.Emit(OpCodes.Ldstr, "MyBinaryData");
ilg.EmitCall(OpCodes.Callvirt, getMRS, null);
// Store the Stream instance.
ilg.Emit(OpCodes.Stloc_0);
// Create a label, and associate it with this point
// in the emitted code.
Label loop = ilg.DefineLabel();
ilg.MarkLabel(loop);
// Load the Stream instance onto the stack, and call
// its ReadByte method. The return value is on the
// stack now; store it in location 1 (variable b).
ilg.Emit(OpCodes.Ldloc_0);
ilg.EmitCall(OpCodes.Callvirt, rByte, null);
ilg.Emit(OpCodes.Stloc_1);
// Load the value on the stack again, and call the
// WriteLine method to print it.
ilg.Emit(OpCodes.Ldloc_1);
ilg.EmitCall(OpCodes.Call, write, null);
// Load the value one more time; load -1 (minus one)
// and compare the two values. If return value from
// ReadByte was not -1, branch to the label 'loop'.
ilg.Emit(OpCodes.Ldloc_1);
ilg.Emit(OpCodes.Ldc_I4_M1);
ilg.Emit(OpCodes.Ceq);
ilg.Emit(OpCodes.Brfalse_S, loop);
// When all the bytes in the stream have been read,
// return. This is the end of Main.
ilg.Emit(OpCodes.Ret);
// Create the type "Example" in the dynamic assembly.
tb.CreateType();
// Because the manifest resource was added as an open
// stream, the data can be written at any time, right up
// until the assembly is saved. In this case, the data
// consists of five bytes.
ms.Write(new byte[] { 105, 36, 74, 97, 109 }, 0, 5);
ms.SetLength(5);
// Set the Main method as the entry point for the
// assembly, and save the assembly. The manifest resource
// is read from the memory stream, and appended to the
// end of the assembly. You can open the assembly with
// Ildasm and view the resource header for "MyBinaryData".
asmBuilder.SetEntryPoint(main);
asmBuilder.Save(asmName.Name + ".exe");
Console.WriteLine("Now run EmittedManifestResourceAssembly.exe");
}
}
/* This code example doesn't produce any output. The assembly it
emits, EmittedManifestResourceAssembly.exe, produces the following
output:
105
36
74
97
109
-1
*/
Imports System.Reflection
Imports System.Reflection.Emit
Imports System.IO
Public Class Example
Public Shared Sub Main()
' Define a dynamic assembly with one module. The module
' name and the assembly name are the same.
Dim asmName As New AssemblyName("EmittedManifestResourceAssembly")
Dim asmBuilder As AssemblyBuilder = _
AppDomain.CurrentDomain.DefineDynamicAssembly( _
asmName, _
AssemblyBuilderAccess.RunAndSave _
)
Dim modBuilder As ModuleBuilder = _
asmBuilder.DefineDynamicModule( _
asmName.Name, _
asmName.Name + ".exe" _
)
' Create a memory stream for the unmanaged resource data.
' You can use any stream; for example, you might read the
' unmanaged resource data from a binary file. It is not
' necessary to put any data into the stream right now.
Dim ms As New MemoryStream(1024)
' Define a public manifest resource with the name
' "MyBinaryData, and associate it with the memory stream.
modBuilder.DefineManifestResource( _
"MyBinaryData", _
ms, _
ResourceAttributes.Public _
)
' Create a type with a public static Main method that will
' be the entry point for the emitted assembly.
'
' The purpose of the Main method in this example is to read
' the manifest resource and display it, byte by byte.
'
Dim tb As TypeBuilder = modBuilder.DefineType("Example")
Dim main As MethodBuilder = tb.DefineMethod( _
"Main", _
MethodAttributes.Public Or MethodAttributes.Static _
)
' The Main method uses the Assembly type and the Stream
' type.
Dim asm As Type = GetType([Assembly])
Dim str As Type = GetType(Stream)
' Get MethodInfo objects for the methods called by
' Main.
Dim getEx As MethodInfo = asm.GetMethod("GetExecutingAssembly")
' Use the overload of GetManifestResourceStream that
' takes one argument, a string.
Dim getMRS As MethodInfo = asm.GetMethod( _
"GetManifestResourceStream", _
New Type() {GetType(String)} _
)
Dim rByte As MethodInfo = str.GetMethod("ReadByte")
' Use the overload of WriteLine that writes an Int32.
Dim write As MethodInfo = GetType(Console).GetMethod( _
"WriteLine", _
New Type() {GetType(Integer)} _
)
Dim ilg As ILGenerator = main.GetILGenerator()
' Main uses two local variables: the instance of the
' stream returned by GetManifestResourceStream, and
' the value returned by ReadByte. The load and store
' instructions refer to these locals by position
' (0 and 1).
Dim s As LocalBuilder = ilg.DeclareLocal(str)
Dim b As LocalBuilder = ilg.DeclareLocal(GetType(Integer))
' Call the static Assembly.GetExecutingAssembly() method,
' which leaves the assembly instance on the stack. Push the
' string name of the resource on the stack, and call the
' GetManifestResourceStream(string) method of the assembly
' instance.
ilg.EmitCall(OpCodes.Call, getEx, Nothing)
ilg.Emit(OpCodes.Ldstr, "MyBinaryData")
ilg.EmitCall(OpCodes.Callvirt, getMRS, Nothing)
' Store the Stream instance.
ilg.Emit(OpCodes.Stloc_0)
' Create a label, and associate it with this point
' in the emitted code.
Dim theLoop As Label = ilg.DefineLabel()
ilg.MarkLabel(theLoop)
' Load the Stream instance onto the stack, and call
' its ReadByte method. The return value is on the
' stack now; store it in location 1 (variable b).
ilg.Emit(OpCodes.Ldloc_0)
ilg.EmitCall(OpCodes.Callvirt, rByte, Nothing)
ilg.Emit(OpCodes.Stloc_1)
' Load the value on the stack again, and call the
' WriteLine method to print it.
ilg.Emit(OpCodes.Ldloc_1)
ilg.EmitCall(OpCodes.Call, write, Nothing)
' Load the value one more time; load -1 (minus one)
' and compare the two values. If return value from
' ReadByte was not -1, branch to the label 'loop'.
ilg.Emit(OpCodes.Ldloc_1)
ilg.Emit(OpCodes.Ldc_I4_M1)
ilg.Emit(OpCodes.Ceq)
ilg.Emit(OpCodes.Brfalse_S, theLoop)
' When all the bytes in the stream have been read,
' return. This is the end of Main.
ilg.Emit(OpCodes.Ret)
' Create the type "Example" in the dynamic assembly.
tb.CreateType()
' Because the manifest resource was added as an open
' stream, the data can be written at any time, right up
' until the assembly is saved. In this case, the data
' consists of five bytes.
ms.Write(New Byte() {105, 36, 74, 97, 109}, 0, 5)
ms.SetLength(5)
' Set the Main method as the entry point for the
' assembly, and save the assembly. The manifest resource
' is read from the memory stream, and appended to the
' end of the assembly. You can open the assembly with
' Ildasm and view the resource header for "MyBinaryData".
asmBuilder.SetEntryPoint(main)
asmBuilder.Save(asmName.Name + ".exe")
Console.WriteLine("Now run EmittedManifestResourceAssembly.exe")
End Sub
End Class
' This code example doesn't produce any output. The assembly it
' emits, EmittedManifestResourceAssembly.exe, produces the following
' output:
'
'105
'36
'74
'97
'109
'-1
'
注解
程序集清单中记录的资源可以是托管资源或清单资源 BLOB,其中每个资源都可以通过链接或嵌入包含在程序集中。 动态程序集支持这四种方案。
此方法允许将清单资源 BLOB 嵌入动态程序集。
若要将托管资源嵌入到动态程序集的清单模块或附属模块中,请使用 ModuleBuilder.DefineResource 方法获取资源编写器,并使用 ResourceWriter.AddResource 方法添加资源。
若要将托管资源链接到动态程序集,请使用 AssemblyBuilder.DefineResource 方法获取资源编写器,并使用 ResourceWriter.AddResource 方法添加链接资源。
若要将清单资源 BLOB 链接到动态程序集,请使用 AssemblyBuilder.AddResourceFile 方法添加链接的资源。
此外,可以使用 方法或 ModuleBuilder.DefineUnmanagedResource 方法将单个 Win32 资源附加到程序集AssemblyBuilder.DefineUnmanagedResource。 此资源不会显示在程序集清单中。
适用于
另请参阅
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈