受限环境下能否在编译时不使用反射获取程序集信息?
编译时从AssemblyInfo.cs获取属性的解决方案
我懂你在低信任环境下没法用反射读取程序集信息的困扰——毕竟反射在受限环境里经常被禁。下面几个编译时的方案,能帮你把AssemblyInfo里的产品名称等属性直接嵌入代码,完全不用运行时反射:
方案1:手动同步常量(简单直接)
这是最基础的方式,适合小型项目:
- 在
AssemblyInfo.cs里保留原有的属性定义:[assembly: AssemblyProduct("MyCoolProduct")] [assembly: AssemblyVersion("1.0.0.0")] - 新建一个静态类,把需要的属性值定义成常量:
public static class AppMetadata { public const string ProductName = "MyCoolProduct"; public const string Version = "1.0.0.0"; } - 之后直接在代码里用
AppMetadata.ProductName就行。缺点是要手动同步两处的内容,容易漏更,但胜在简单无依赖。
方案2:用MSBuild自动生成代码(推荐自动化方案)
这个方案能在编译时自动读取AssemblyInfo.cs的属性,生成包含常量的代码文件,完全不用手动维护:
- 打开你的项目文件(
.csproj),在<Project>标签内添加以下MSBuild目标:<Target Name="GenerateAppMetadata" BeforeTargets="CoreCompile"> <!-- 读取AssemblyInfo.cs的内容 --> <ReadLinesFromFile File="$(MSBuildProjectDirectory)\Properties\AssemblyInfo.cs"> <Output TaskParameter="Lines" ItemName="AssemblyInfoContent" /> </ReadLinesFromFile> <!-- 用正则提取产品名称、版本等属性 --> <PropertyGroup> <ExtractedProductName>$([System.Text.RegularExpressions.Regex]::Match('@(AssemblyInfoContent)', '\[assembly:\s*AssemblyProduct\s*\(\s*"([^"]+)"\s*\)\]').Groups[1].Value)</ExtractedProductName> <ExtractedVersion>$([System.Text.RegularExpressions.Regex]::Match('@(AssemblyInfoContent)', '\[assembly:\s*AssemblyVersion\s*\(\s*"([^"]+)"\s*\)\]').Groups[1].Value)</ExtractedVersion> </PropertyGroup> <!-- 生成自动代码文件 --> <WriteLinesToFile File="$(IntermediateOutputPath)\AppMetadata.g.cs" Lines=' namespace YourProjectNamespace { public static class AppMetadata { public const string ProductName = "$(ExtractedProductName)"; public const string Version = "$(ExtractedVersion)"; } }' Overwrite="true" /> <!-- 把生成的文件加入编译 --> <ItemGroup> <Compile Include="$(IntermediateOutputPath)\AppMetadata.g.cs" /> </ItemGroup> </Target> - 替换
YourProjectNamespace为你项目的实际命名空间。 - 重新编译项目,MSBuild会自动在中间输出目录生成
AppMetadata.g.cs,你直接在代码里用AppMetadata.ProductName即可。
方案3:用T4模板生成代码(灵活可控)
T4模板是Visual Studio自带的文本生成工具,能灵活读取文件并生成代码:
- 在项目里新建一个T4模板文件(比如
AppMetadata.tt),写入以下内容:<#@ template language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.IO" #> <#@ import namespace="System.Text.RegularExpressions" #> namespace YourProjectNamespace { public static class AppMetadata { public const string ProductName = "<#= GetAssemblyAttribute("AssemblyProduct") #>"; public const string Version = "<#= GetAssemblyAttribute("AssemblyVersion") #>"; } } <#+ // 从AssemblyInfo.cs提取指定属性的方法 private string GetAssemblyAttribute(string attributeName) { var assemblyInfoPath = Path.Combine(Host.ResolvePath("."), "Properties", "AssemblyInfo.cs"); if (!File.Exists(assemblyInfoPath)) return string.Empty; var fileContent = File.ReadAllText(assemblyInfoPath); var regexMatch = Regex.Match(fileContent, $@"\[assembly:\s*{attributeName}\s*\(\s*""([^""]+)""\s*\)\]"); return regexMatch.Success ? regexMatch.Groups[1].Value : string.Empty; } #> - 右键模板文件,设置自定义工具为
TextTemplatingFileGenerator。 - 保存模板,Visual Studio会自动生成
AppMetadata.cs文件,里面包含你需要的属性常量,直接调用即可。
这些方案都是在编译阶段把AssemblyInfo的属性值嵌入到代码中,运行时完全不需要反射,完美适配低信任环境的限制。
内容的提问来源于stack exchange,提问作者Boris Zinchenko
相关产品推荐
相关产品推荐

