【问题标题】:use a string variable to address a struct field使用字符串变量来寻址结构字段
【发布时间】:2020-03-31 00:49:13
【问题描述】:

在 C# 中,我有一个包含许多字段的结构,例如一种叫做“钥匙”。我正在阅读一个 .ini 设置文件,其中包含所有结构字段的值。有没有办法在读取过程中使用字段名称作为字符串(如下面的 myField 字符串数组)来寻址结构字段(见下文)?这将允许我在基于字符串数组的循环中迭代读取许多字段。

private struct Foo {
  public string key;
  ...
}

private Foo FooInstance;
string inStr;
string[] myFields[] = new string[10]{ ("key", "nextKey", ... );

for (int i=0;i<myFields.Length;i++) {
  GetPrivateProfileString(section,myFields[i],"",inStr,255,file);
  [convert myField[i] to the relevant Foo.key field] = inStr;
}

【问题讨论】:

  • “我有一个包含很多字段的结构” - 实际上不建议使结构超过 16 个字节
  • 您在重新发明config 文件吗?为什么不是 JSON 和 newtonsoft,它们会为你序列化/反序列化?
  • 这是一种糟糕的编码实践。在这种情况下,您确实应该至少将数据存储在 Dictionary 中。您标记为最佳的答案在技术上是正确的,但解决您的问题的方法非常糟糕。非必要时应避免反射

标签: c# struct field ini


【解决方案1】:

结合 this SO answer 中的反射技术,并记住 struct 是一种值类型,因此您需要在更新后将其传递回 correctly handle

一个非常快速的解决方案可能如下所示:

struct Foo { 
    public string Key;
    public string NextKey;
}
static class FooExtensions
{
    public static void Set(this ref Foo obj, string key, string value) {
        object boxed = obj; // need to box the value type so we can use it after SetValue  
        var f = typeof(Foo).GetField(key, BindingFlags.Public|BindingFlags.Instance);
        f.SetValue(boxed, value);
        obj = (Foo) boxed;
    }

    public static string Get(this Foo obj, string key)
    {
        var f = typeof(Foo).GetField(key, BindingFlags.Public|BindingFlags.Instance);
        return (string)f.GetValue(obj);
    }
}
void Main()
{   
    var f = default(Foo);   
    f.Set("Key", "test");
    f.Set("NextKey", "test");   
    f.Get("Key").Dump();
}

【讨论】:

  • 谢谢。在您链接到的答案中,有这一行(我为命名而对其进行了修改)。它不会以更简单的内联方式与您的扩展做同样的事情吗?FooInstance.GetType().GetField("key").SetValueDirect(__makeref(FooInstance), inStr)
  • 可能,它看起来非常相似,我还没有测试过。我个人觉得扩展方法很容易处理。请记住,您需要正确的 BindingFlags 来获取字段并注意那个拳击陷阱
  • Set() 扩展有效,但 Get() 给了我这个异常: System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.String' at Example.FeedExtensions .Get(Foo obj,字符串键)。知道有什么问题吗?谢谢。
  • @MrSparkly 您的 Foo 可能有一个整数值,其中 Get 假定它始终是一个字符串。尝试在方法中使用 Convert.ToString() 而不是直接强制转换?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-19
  • 1970-01-01
  • 2016-07-11
  • 2012-04-27
  • 1970-01-01
相关资源
最近更新 更多