使用AssemblyBuilder构建资源程序集

时间:2011-12-26 10:10:39

标签: c# dynamic resources .net-assembly

场景:我想创建属于资源程序集的附属程序集。           该程序集仅在其中编译资源(ResourceWriter)。           目标是在VS之外创建资源程序集并将它们添加到应用程序中,并将其添加到我的C#应用​​程序中

我正在使用AssemblyBuilder来创建程序集。它有效,但没有关于存储的程序集的信息。没有cultureinfo,密钥或其他任何东西。程序集不会使用Missing Manfifest Resource Exception。 :(

如果可能,我想继续使用AssemblyBuilder或使用CodeDomProvider。

问题:为我的应用添加新的卫星组件有什么必要?是否有足够的文件夹(en-US)和包含en-US资源的程序集?

问题2 :是否可以向大会提供一些元信息,如版本,文化?

问题3 :是否足以将资源添加到程序集中?

代码:

AssemblyBuilder builder = AppDomain.CurrentDomain.DefineDynamicAssembly(
                        assemblyName, AssemblyBuilderAccess.RunAndSave, resourceFolder);

builder.AddResourceFile(name, assemblyFileName);
builder.Save(assemblyName.Name);

对于任何形式的帮助,我将不胜感激。 提前致谢

2 个答案:

答案 0 :(得分:7)

找到解决方案。

来源:http://www.dotnet247.com/247reference/msgs/58/290731.aspx

说明:首先看来 AssemblyBuilder只将资源链接到程序集,它没有嵌入。其次,资源必须位于模块中才能被主程序集看到。 (我不喜欢在模块中创建资源,但似乎没有办法嵌入已有的资源)

守则:

        string myAsmName = "WriteSatelliteAssembly.resources";
        string myAsmFileName = myAsmName + ".dll";
        string resourceName = "WriteSatelliteAssembly.MyResource2.fr.resources";
        string path;

        path = AppDomain.CurrentDomain.BaseDirectory + "fr-FR";
        AppDomain appDomain = Thread.GetDomain();
        AssemblyName asmName = new AssemblyName();
        asmName.Name = myAsmName;
        asmName.CodeBase = path;
        asmName.CultureInfo = new CultureInfo("fr");

        AssemblyBuilder myAsmBuilder = appDomain.DefineDynamicAssembly(
            asmName,
            AssemblyBuilderAccess.RunAndSave, path);

        **ModuleBuilder** myModuleBuilder =
            myAsmBuilder.DefineDynamicModule(myAsmFileName,
            myAsmFileName);
        **IResourceWriter** rw =
            myModuleBuilder.DefineResource(resourceName,
            "My Description",ResourceAttributes.Public);

        rw.AddResource("resName","My (dynamic) resource value.");
        rw.AddResource("resName2","My (dynamic) second resource value.");

        myAsmBuilder.Save(myAsmFileName);

证明短信:

汇编中的链接资源

.file nometadata 'TestProjectResourceManager.Properties.Resources.en-US.resources'
    .hash = (57 DD 82 37 9E B3 BA 8A 27 D0 69 90 37 67 22 23   // W..7....'.i.7g"#
             A0 1C F7 47 )                                     // ...G
.mresource public TestProjectResourceManager.Properties.Resources
{
  .file 'TestProjectResourceManager.Properties.Resources.en-US.resources' at 0x00000000
}
装配中的

嵌入式资源

.mresource public 'TestProjectResourceManager.Properties.Resources.en-US.resources'
{
  // Offset: 0x00000000 Length: 0x000000EE
}
.module TestProjectResourceManager_2.resources.dll

玩得开心

答案 1 :(得分:2)

您需要以下工具来创建装配体。

  1. resgen.exe
  2. Al.exe工具
  3. 程序Ildasm.exe
  4. al.exe是将资源嵌入附属程序集的程序。但al.exe只接受.resources二进制格式的资源。但我们的输入通常是纯文本资源文件或.resx格式的基于XML的资源文件。 resgen.exe用于将这些替代形式的资源转换为适合al.exe的.resources二进制格式。

    ildasm.exe:如果您还记得Visual Studio IDE正在做什么,您将看到资源文件目录结构与程序集内部资源文件的知道方式之间存在名称转换。我们使用Visual Studio IDE生成默认资源和生成附属程序集的外部过程,这两种机制必须生成具有相同资源文件命名层次结构的程序集。

    因此,我们使用ildasm检查Visual Studio IDE生成的DLL,以找出结构是什么,并使用相同的机制生成附属程序集。您还可以使用ildasm检查附属程序集,以确保您获得正确的名称。这对于调试资源管理器中的错误非常有用,它告诉您它无法找到资源。

    现在已经概述了这些工具,我们如何将外部资源文件转换为附属程序集?如下所述,这是一个三个(实际上是两个)步骤。

    步骤0:设置resgen和al.exe的路径:

    @set path=%path%;
        "C:\Program Files\Microsoft Visual Studio .NET\FrameworkSDK\Bin";
         c:\winnt\microsoft.NET\framework\v1.0.3705
    

    步骤1:使用resgen从.resx文件创建.resources文件。

    Resgen MyText.resx
    

    上面的命令将创建一个名为:

    的文件
    MyText.resources
    

    步骤2:使用al.exe创建附属程序集:

    Al.exe
         /t:lib
         /embed:MyText.en-gb.Resources,MyApplication.MyText.en-gb.Resources
         /culture:hi-gb
         /out:MyApplication.resources.dll
    

    这里有一些值得注意的事情:

    /t:lib: Says you are interested in a .dll.
    
    /embed:MyText.en-gb.Resources,MyApplication.MyText.en-gb.Resources : Embeds and renames the resource to a target name to match the Visual Studio IDE naming structure.
    
    /culture:hi-gb : Identifies the culture in which you are interested.
    
    /out:MyApplication.resources.dll : Name of the DLL in which you are interested.
    

    生成的.dll必须具有.NET的命名约定才能找到它。另请注意,您必须指定区域性设置,即使文化在资源文件的名称中可用。因此必须在两个地方都提到它。

    将Satellite Assembly放在适当的目录中 创建附属程序集后,将.dll物理复制到以下目录:

    \MyApplication\bin\en-gb\MyApplication.Resources.DLL
    

    如果有多个资源文件:

    \MyApplication\resources\files\CommonResources.resx
    \MyApplication\resources\files\Module1Resources.resx
    \MyApplication\resources\files\Module2Resources.resx
    

    您可以在单独的层次结构中定义这些资源的密钥,如下所示:

    \MyApplication\resources\keys\CommonKeys.cs
    \MyApplication\resources\keysModule1Keys.cs
    \MyApplication\resources\keys\Module2Keys.cs
    

    对于批处理程序脚本,请参阅我的博客 http://samithenerd.blogspot.com/2011/12/batch-program-for-creating-satellite.html