如何在.NET Core 2类库项目中使用C#从.csproj文件中读取/获取PropertyGroup值?

12
我希望使用C#获取.NET Core 2 classlib项目的.csproj文件中的子元素<Location>SourceFiles/ConnectionStrings.json</Location>的值。其结构如下:
<PropertyGroup>
  <TargetFramework>netcoreapp2.0</TargetFramework>
  <Location>SharedSettingsProvider.SourceFiles/ConnectionStrings.json</Location>
</PropertyGroup>

我应该使用.NET Core库中的哪个类来实现这个功能?(不是.NET框架)

更新1: 我想在应用程序(即此.csproj文件构建的应用程序)运行时读取值。在部署之前和之后都需要。

谢谢


1
你能澄清一下你想做什么吗?你是想在应用程序运行时(可能是在部署到服务器后)读取值吗?还是你有一个单独的应用程序需要从这个csproj文件中读取值?你到底想做什么? - omajid
@omajid,更新1澄清了我的意思。谢谢。 - walter_dl
1
哦,恐怕这是不可能的。csproj文件用于构建,在运行时不存在。因此,您无法从中读取值。您可以在构建期间编写一个配置文件(该配置文件将包含变量/值),并将该配置文件放置在应用程序旁边,以便您的应用程序可以在运行时找到它。 - omajid
1个回答

24

正如在评论中讨论的那样,csproj内容仅控制预定义的构建任务,在运行时不可用。

但是,msbuild很灵活,可以使用其他方法将某些值持久化以便在运行时使用。

一种可能的方法是创建自定义程序集属性:

[System.AttributeUsage(System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)]
sealed class ConfigurationLocationAttribute : System.Attribute
{
    public string ConfigurationLocation { get; }
    public ConfigurationLocationAttribute(string configurationLocation)
    {
        this.ConfigurationLocation = configurationLocation;
    }
}

然后可以在csproj文件内部使用它来生成自动化的程序集属性:

<PropertyGroup>
  <ConfigurationLocation>https://my-config.service/customer2.json</ConfigurationLocation>
</PropertyGroup>
<ItemGroup>
  <AssemblyAttribute Include="An.Example.ConfigurationLocationAttribute">
    <_Parameter1>"$(ConfigurationLocation)"</_Parameter1>
  </AssemblyAttribute>
</ItemGroup>

然后在代码中运行时使用:

static void Main(string[] args)
{
    var configurationLocation = Assembly.GetEntryAssembly()
        .GetCustomAttribute<ConfigurationLocationAttribute>()
        .ConfigurationLocation;
    Console.WriteLine($"Should get config from {configurationLocation}");
}

1
提醒下一位开发者:GetEntryAssembly() 可能与执行程序集不同... - JohnTortugo
1
我无法使用此示例访问类型“ConfigurationLocationAttribute”。如果我在.csproj文件中使用“Compile”标记,则会编译但在运行时不起作用。如果我像这里所示使用“AssemblyAttribute”标记,则无法访问该类型,项目将无法编译(您的Main方法对我来说无法编译)。 - Dan Rayson
1
@DanRayson 你能提供一个完整的例子吗?也许创建一个新的问题?这里唯一没有完全解释的是用 app 使用的命名空间替换 An.Example.。此外,当项目取消激活程序集信息生成时,它将无法工作(但然后应该编译但在运行时失败)。 - Martin Ullrich
1
我们成功地使其运作,按@MartinUllrich的意图设置为:<AssemblyAttribute Include="Namespace.Where.Sealed.Class.Defined.ConfigurationLocationAttribute"> - TrustworthySystems
澄清一下julealgon和martin-ullrich的评论: 答案提出的方法适用于任何TFM(即.NET Framework),只要您使用SDK-style项目。 对于非SDK-style项目,您可能需要采用不同的方法,因为在SDK-style项目开始支持.NET Framework TFM之前(大约在2019年左右),历史上必须使用它们来进行.NET Framework项目。 - svenhuebner
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接