gpt4 book ai didi

c# - 在 .net core 3.1 类库项目中的构建时设置具有某个值的类私有(private)字符串参数

转载 作者:行者123 更新时间:2023-12-02 02:44:03 26 4
gpt4 key购买 nike

我的 .NET Core 3.1 库项目中有一个类,我想在构建时初始化字段 key:

using System.Text;

namespace MyNamespace
{
public class Myclass
{
private string key;

....
}
}

我正在通过简单的发布命令发布我的库:

dotnet publish -c release -r linux-x64

我正在探索一个选项,我可以在构建期间传递一些属性,这些属性将在编译/构建过程中在关键属性中设置。

在此过程之后,我还通过一些第三方工具对我的 DLL 进行了混淆。

然后,该 DLL 将嵌入到应用程序中,其中通过反射调用该类的一个方法(反射和调用方法已经完成)。

最佳答案

使用 Roslyn API,您可以通过编程方式解析和编译源代码。 The question linked by vasil oreshenski为您提供工作示例。缺少的部分是(以某种方式)获得所需的值,然后在编译之前将其嵌入到语法树中。

首先,为了让我们的生活更轻松,创建一个自定义属性并用它标记关键字段。

using System;

public class BuildTimeParameterAttribute : Attribute
{
}
namespace MyNamespace
{
public class Myclass
{
[BuildTimeParameter]
private const string key1 = "", key2 = "";

[BuildTimeParameter]
private const string key3 = "";

....
}
}

我还将该字段更改为 const 并添加了其他字段来测试行为。现在,当您拥有来自 RoslynAPI 的语法树时,您可以执行以下操作:

var parsedSyntaxTree = Parse(
source,
"",
CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp8));

// Get those values from commandline arguments or however you like.
var replacementValues = new Dictionary<string, string>
{{"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}};

var root = (CompilationUnitSyntax) parsedSyntaxTree.GetRoot();
// Retrieve all fields marked with the BuildTimeParameterAttribute.
var fields = root.DescendantNodes().OfType<FieldDeclarationSyntax>().Where(
s => s.AttributeLists.SelectMany(a => a.Attributes)
.Any(a => a.Name.ToString() == "BuildTimeParameter"));

var newRoot = root.ReplaceNodes(
fields,
(_, field) =>
{
var variables = field.Declaration.Variables;
var newVariables = from variable in variables
let newValue = replacementValues[variable.Identifier.ValueText]
let newInitializer = variable.Initializer.WithValue(
SyntaxFactory.LiteralExpression(
SyntaxKind.StringLiteralExpression,
SyntaxFactory.Literal(newValue)))
select variable.WithInitializer(newInitializer);

return field.WithDeclaration(
field.Declaration.WithVariables(
SyntaxFactory.SeparatedList(newVariables)));
});

该过程有点复杂,因为单个字段声明可以包含许多变量(在我们的例子中,第一个字段声明包含 key1key2)。

现在您可以使用newRoot.SyntaxTree 创建编译。反编译生成的 dll 会产生:

namespace MyNamespace
{
public class MyClass
{
[BuildTimeParameter]
private const string key1 = "value1";
[BuildTimeParameter]
private const string key2 = "value2";
[BuildTimeParameter]
private const string key3 = "value3";
}
}

上面的代码不处理错误,如果没有初始化程序,则会失败并出现 NRE,例如,如果您编写 private string key;。它将与 const 一起使用,因为它们需要有一个初始值设定项。让这段代码具有生产值(value),我留给您。

注意

在 .NET 5 中,使用 source generators 可以更轻松地完成此操作。 。您可以将类声明为 partial,然后使用源生成器生成带有 key 常量字段声明的文件。

关于c# - 在 .net core 3.1 类库项目中的构建时设置具有某个值的类私有(private)字符串参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63097655/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com