我的应用程序将涉及静态字段的大量修改.我想知道如何通过将来自不同类的静态字段作为方法参数传递给实用程序setter方法来更新它们.

internal static class Hero1
{
  public static bool awesomeAbility = false;
  public static bool anotherAwesomeAbility = false;
}

internal static class Hero2
{
  public static bool awesomeAbility = false;
  public static bool anotherAwesomeAbility = false;
}

internal static class Utils
{
  public static async void ToggleAbility(ability, bool value)
  {
    Logger.Write($@"{ability} = {value}");
    ability = value;
  }
}

// example usage....
ToggleAbility(Hero1.awesomeAbility, true);
ToggleAbility(Hero2.anotherAwesomeAbility, false);

推荐答案

如果您允许调用者传递一个表达式树(Expression<Func<bool>>),则可以这样做,然后您可以获得由表达式树引用的字段FieldInfo.

async void ToggleAbility(Expression<Func<bool>> field, bool value) {
    if (field.Body is MemberExpression memberExpression &&
        memberExpression.Member is FieldInfo fieldInfo) {
        
        // instead of field.Body, you can also use fieldInfo.Name for a simple name
        Logger.Write($@"{field.Body} = {fieldInfo.GetValue(null)}");

        // this sets the field's value
        fieldInfo.SetValue(null, value);

        // if you want to set it back asynchronously some time later...
        // await Task.Delay(...);
        // fieldInfo.SetValue(null, !value);
    } else {
        // the expression tree is not an access to a public static field
        // you could e.g. throw an exception 
    }
}

用途:

ToggleAbility(() => Hero1.awesomeAbility, true);

将字段设置为SetValue并不是很快.如果这对你来说是个问题,你可以 Select "野战二传手"Action<bool>

async void ToggleAbility(Action<bool> setter, bool value) {
    setter(value)
    await Task.Delay(...);
    setter(!vakue)
}
ToggleAbility(x => Hero1.awesomeAbility = x, true);

但是,您不能使用此方法访问字段名称或其当前值(以ToggleAbility为单位),除非您还将它们作为附加参数传递:

ToggleAbility(
    x => Hero1.awesomeAbility = x, 
    true,
    nameof(Hero1.awesomeAbility),
    Hero1.awesomeAbility);

如果您的方法不需要是异步的,您还可以将该字段作为ref参数传递,如lidqy的答案所示.

Csharp相关问答推荐

当前文化和当前文化之间没有区别IgnoreCase,为什么?

ASP.NET Core -如何解决Fluent验证中无法访问的扩展方法Message Formatter错误

System. InvalidOperationException:无法将数据库中的字符串值i转换为映射的ItemType枚举中的任何值''''

我需要两个属性类吗

实现List T,为什么LINQ之后它不会返回MyList?<>(无法强制转换WhereListIterator `1类型的对象)'

在命名管道上使用GRPC ASP.NET核心时如何配置命名管道权限

如何使用MoQ模拟Resources GroupCollection?

为基本审计设置Audit.EntityFramework.Core

如何使用XmlSerializer序列化带有CDATA节的XML文件?

使用Dapper映射联接查询对象数据到使用SplitOn;

为什么@rendermode Interactive Auto不能在.NET 8.0 Blazor中运行?

.NET:从XPath定位原始XML文档中的 node

.NET 6:如何防止系统生成的日志(log)?

为什么我可以在注册表编辑器中更改值,但不能在以管理员身份运行的C#表单应用程序中更改?

如何从SignalR获取连接客户端的域

Linq SELECT的多条指令

映射器-如何映射到多个实体

如何在Cake脚本中设置MSBuild.exe的绝对路径

如何使用LINQ在C#中填充列表列表?

将文本从剪贴板粘贴到RichTextBox时,新文本不会在RichTextBox ForeColor中着色