【问题标题】:Replacement of switch statement - getting properties via a string name替换 switch 语句 - 通过字符串名称获取属性
【发布时间】:2014-03-05 10:13:12
【问题描述】:

基本上,我有一个系统,我的数据网格用新的背景颜色标记已更改的单元格,为此,我在包含这些属性的对象中有一个方法,该方法接收一个字符串,该字符串是属性的名称进行检查,然后是一个 switch 语句,该语句使用该字符串来检查正确的属性。

public Color HasChanged(string value)
{
    switch (value)
    {
        case "CILRef":
            if (_localShipment.cilRef != _originalShipment.cilRef)
            {
                return Colors.SkyBlue;
            }
            else
            {
                return Colors.White;
            }
        case "ArrivedAtPortDate":
            if (_localShipment.arrivedAtPortDate != _originalShipment.arrivedAtPortDate)
            {
                return Colors.SkyBlue;
            }
            else
            {
                return Colors.White;
            }
    }
}

为简洁起见,我删除了其余属性。

现在我有一种烦人的感觉,即有一种更简洁的方式来处理这个字符串>属性,而不使用 switch 语句,但我一生都无法在谷歌上找到任何东西,如果没有一些关键字就很难搜索到继续。

我还试图只保存那些已更改的属性,我打算将任何更改的属性名称放入一个数组中,然后使用另一个检查该数组的 switch 语句进行循环,然后保存正确的属性.然而,这对我来说又显得不整洁。

有没有更简洁的解决方案,希望可以处理添加新属性而无需向 switch 语句添加新代码。

如果需要,我可以包含执行此检查的其余代码(即数据网格上的 WPF 绑定,以及使用属性名称作为字符串参数调用检查方法的转换器)。

【问题讨论】:

  • @James -- 在 OP 中:“为简洁起见,我删除了其余属性。”

标签: c# wpf switch-statement


【解决方案1】:

你可以写一个扩展方法,比如:

public static object GetPropValue(this object o, string propName)
{
    return o.GetType().GetProperty(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase)
            .GetValue(o);
}

并使用它

if(localShipment.GetPropValue(value).Equals(originalShipment.GetPropValue(value)))
{
}

【讨论】:

  • 啊,这正是我想要的!我得试试这个。
  • 我在上面的代码中遇到一个错误,“方法 'GetValue' 没有重载需要 1 个参数”
  • @user1412240 try .GetValue(o,null); 您必须使用旧版本的 .Net
  • 是的,很抱歉,我在发布该评论后解决了问题,我坚持使用 .net 4.0,因为我只有 vs2010 许可。
【解决方案2】:

您可以为您的属性定义一个通用接口,然后创建一个属性字典,如下所示:

var properties = new Dictionary<string, IProperty>();

并像这样访问它们:

properties["CILRef"]

【讨论】:

  • 这是一个非常好的主意,如果将属性添加到此模型中,它肯定有助于解决必须不断添加代码的次要问题。我会玩这个。
【解决方案3】:

我想说switch 语句很好,但是,您可以使用condition operator 在单行中完成case 的主体

switch (value)
{
    case "CILRef":
        return _localShipment.cilRef != _originalShipment.cilRef ? Colors.SkyBlue : Colors.White;
    case "ArrivedAtPortDate":
        return _localShipment.arrivatedAtPortDate != _originalShipment.arrivedAtPortDate ? Colors.SkyBlue : Colors.White;
    ...
}

但是你仍然会有重复的代码,你可以更进一步,有一个 GetColor 方法在

public Colors GetColor(Func<bool> condition)
{
    return condition() ? Colors.SkyBlue : Colors.White;
}
...
switch (value)
{
    case "CILRef":
        return GetColor(() => _localShipment.cilRef != _originalShipment.cilRef);
    case "ArrivedAtPortDate":
        return GetColor(() => _localShipment.arrivatedAtPortDate != _originalShipment.arrivedAtPortDate);
}

仔细查看您的代码,您似乎确实在比较每次运输的相同属性,您可以使用反射将其减少为一次检查

public Color HasChanged(string value)
{
    var date1 = _localShipment.GetType()
        .GetProperty(value)
        .GetValue(_localShipment, null);
    var date2 = _originalShipment.GetType()
        .GetProperty(value)
        .GetValue(_originalShipment, null);
    return date1 != date2 ? Colors.SkyBlue : Colors.White;
}

为简洁起见,您可以创建一个扩展方法来包装反射部分

public static T Get<T>(this object obj, string name)
{
    return obj.GetType().GetProperty(name).GetValue(obj, null);
}
...
return _localShipment.Get<DateTime>(value) != _originalShipment.Get<DateTime>(value) ? Colors.SkyBlue : Colors.White;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-11
    • 1970-01-01
    • 2021-08-02
    • 2012-05-04
    • 1970-01-01
    相关资源
    最近更新 更多