【问题标题】:How to to transform a String of Property Names into an object's Property Values如何将属性名称字符串转换为对象的属性值
【发布时间】:2016-05-08 15:48:40
【问题描述】:

我的许多类都有一个使用字符串插值的 DisplayName 属性,例如:

  DisplayName = $"{CutoutKind} {EdgeKind} {MaterialKind}";

其中 {} 中的每个元素都是一个类属性名称。

我想做的是从数据库中检索正在插入的字符串,例如

displayName = SomeFunction(StringFromDatabase, this);

其中 StringFromDatabase 是一个变量,值从数据库中设置,= "{CutoutKind} {EdgeKind} {MaterialKind}"

但是我想在不使用反射的情况下做到这一点

有什么不同的方法可以实现我想要的吗?

【问题讨论】:

  • 你能告诉你整个班级吗?您还希望将类上的 DisplayName 属性设置为数据库中的值,这是问题吗?我不明白你所说的字符串插值是什么意思..
  • 你的问题不清楚,但我认为你可以在每个类中重写 ToString() 函数并编写自己的函数。如果所有类中的函数都与基类中固有的相同
  • 如果您将内插字符串分配给FormattableString,您可以手动处理它。即FormattableString x = $"...";.
  • @markmnl 字符串插值由 C# 运算符 '$' 执行
  • @Mahdi 我不确定什么不清楚?

标签: c# properties


【解决方案1】:

在运行时执行此操作而不使用反射意味着无法使用通用解决方案。您必须为要支持的每个类编写不同的方法。一个非常简单的版本:

static string SomeFunction(string format, MyClass instance)
{
    return format.Replace("{CutoutKind}", instance.CutoutKind.ToString())
                 .Replace("{EdgeKind}", instance.EdgeKind.ToString())
                 .Replace("{EdgeKind}", instance.MaterialKind.ToString());
}

或者稍微复杂一点的版本:

Dictionary<string, Func<MyClass, string>> propertyGetters = 
    new Dictionary<string, Func<MyClass, string>>
    {
        { "CutoutKind", x => x.CutoutKind.ToString() }
        { "EdgeKind", x => x.EdgeKind.ToString() }
        { "EdgeKind", x => x.MaterialKind.ToString() }
    };

static string SomeFunction(string format, MyClass instance)
{
    return Regex.Replace(@"\{(\w+)\}", 
        m => propertyGetters.HasKey(m.Groups[1].Value) 
                 ? propertyGetters[m.Groups[1].Value](instance) 
                 : m.Value;
}

但如果您决定不想为每个类编写这种方法,这里有一个使用反射的简单通用版本:

static string SomeFunction<T>(string format, T instance)
{
    var propertyInfos = typeof(T)
        .GetProperties(BindingFlags.Public | BindingFlags.Instance)
        .ToDictionary(p => p.Name);
    return Regex.Replace(@"\{(\w+)\}", 
        m => propertyInfos.HasKey(m.Groups[1].Value) 
                 ? propertyInfos[m.Groups[1].Value].GetValue(instance, null) 
                 : m.Value;
}

【讨论】:

  • 是的。但我不想使用反射
  • @AndrewBingham 我提供了两个不使用反射的示例。请注意,C# 中的字符串插值仅通过在编译时转换格式字符串起作用。没有反射就无法在运行时真正“伪造”它。
  • @ p.s.w.g.哪些例子不使用反射??
  • @AndrewBingham 前两个示例不使用反射。也许我在第二个示例中将字典命名为 propertyGetters 有点令人困惑,但请注意我使用 lambda 表达式,而不是反映 PropertyInfo's
  • 啊 - 我明白你的意思了。我正在寻找一个“通用”的解决方案,
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-17
相关资源
最近更新 更多