【问题标题】:Different resource files for different client deployments不同客户端部署的不同资源文件
【发布时间】:2013-07-12 14:34:32
【问题描述】:

我正在为 2 个客户开发一个 WinForms 应用程序。客户端之间的区别仅在于品牌:ClientA 获取 LogoA.png。 ClientB 获取 LogoB.png。我需要将应用程序作为安装程序和所有可执行文件的 zip 文件发送给他们。

我正在考虑将图像放在不同的资源文件中,并将它们编译为附属程序集并在构建服务器上,当我生成 zip 文件和安装程序时,我只包含用于 ClientA 的 ResourceA 和用于 ClientB 的 ResourceB。这是计划,但我以前从未这样做过。

documentation 表示资源文件应由语言和文化代码标识。我的两个客户都将用英语(en-GB 或 en-US)运行他们的机器。我可以忽略推荐并以客户的名义调用资源。但是它们会被应用程序拾取吗? (假设只有一个资源文件,机器文化与资源文化代码不匹配)。

有没有更好的解决方案?

附言我知道编译器指令,但它使代码变得笨拙和肮脏。将来,客户可能会在屏幕上显示不同的文本,这就是资源的完美案例。

【问题讨论】:

    标签: c# winforms deployment resources


    【解决方案1】:

    您可以为每个公司创建单独的构建配置。然后,您可以更改 .csproj 文件以执行 msbuild 任务,该任务将使用选定的公司资源替换默认资源文件,这里是如何检查 msbuild 中的当前配置的示例。

    <PropertyGroup Condition="'$(Configuration)' == 'CompanyABuild'">
      //set resource to point to company A
    </PropertGroup>
    <PropertyGroup Condition="'$(Configuration)' == 'CompanyBBuild'">
        //set resource to point to company B
    </PropertGroup>
    

    【讨论】:

    • 这个问题花费了太多时间。我通过双重编译走上了“肮脏”的道路。
    【解决方案2】:

    您可以将一个用于客户端A 的另一个资源文件添加到单独的资源文件中,另一个用于客户端B(ClientA.resx、Clinetb.resx)。然后在 app.config 文件中添加一个配置条目,其中包含要使用的资源的名称。 然后你需要创建一个包装类,它将根据配置值为你提供资源,你需要使用动态对象和资源管理器,这里是一个示例代码:

     class Program
        {
            static void Main(string[] args)
            {
                var res = new CompanyAResource();
    
                var companyResources = new global::System.Resources.ResourceManager("ConsoleApplication1.CompanyAResource", typeof(CompanyAResource).Assembly);
    
                dynamic resources = new DynamicResources(companyResources);
    
                string name = resources.CompanyName;
    
                Console.WriteLine(name);
    
            }     
        }
    
        public class DynamicResources : System.Dynamic.DynamicObject
        {
            private ResourceManager resources;
    
            public DynamicResources(ResourceManager resources)
            {
                this.resources = resources;
            }      
    
            public override bool TryGetMember(System.Dynamic.GetMemberBinder binder, out object result)
            {
                result = this.resources.GetString(binder.Name);
                return true;
            }      
        }
    

    【讨论】:

    • 我想过。这将涉及部署我想避免的不同客户端配置。这也将允许用户更改 app.config 并使用其他品牌。
    • 如果您不想通过我们的应用程序运送所有资源,则需要为每个公司单独构建。在构建应用程序之前,您可以将资源文件替换为您正在构建的公司,例如,您可以使用 msbuild 任务来自动化流程
    • 我也想到了。但这会违反持续交付的“构建一次”规则。在创建安装程序之前,我宁愿与所有其他程序集同时构建所有资源,并在最后一步中删除额外内容。
    • 无论如何,感谢您对配置的建议。我想我会用资源创建程序集,在主应用程序的同时构建它们。然后通过反射加载它们:扫描应用程序文件夹以查找具有资源的程序集。取一张可用的并从那里加载图像。
    猜你喜欢
    • 2015-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-25
    • 1970-01-01
    • 2013-02-14
    • 2021-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多