如何使用动态默认值处理属性

时间:2009-02-23 23:20:57

标签: c# java

创建简单的数据对象时,我经常遇到这种情况。我有一个名为Label的属性,它应该具有基于对象名称的默认值。因此,如果未设置标签,则使用名称,否则使用set Label。 C#中的一个简单例子

public class FooBat {
    public string Name { get; set; }
    public string Label {
        get {
            if (_label == null) return Name;
            return _label;
        }
        set { _label = value; }
    }
}

现在的问题是,如果你想编辑这个对象,你不能只是绑定到Label属性,或者你将得到默认值,它看起来好像有一个值,当真的没有。所以我最终做的是创建另一个只读属性来执行默认操作,我使用的是除了编辑基础对象之外的所有实例。这导致许多额外的属性与奇怪的名称,如LabelWithDefault。我尝试的另一个替代方法是使Label处理默认值并创建一个名为RealLabel的新属性,用于编辑基础对象。这同样糟糕。

我已经考虑过在其他地方移动默认代码,但我没有在任何“普通”模型中找到一个好地方,它不会多次复制默认代码。

我现在开始做的是在设置Name字段时初始化Label字段(并且Label字段不是),然后将Label字段视为普通字段。这有效,但现在默认代码与错误的属性相关联。为什么Name知道Label字段关心它?所以这也不是“正确的”。

有没有人有更好的方法来处理这个问题?


我认为我要求的内容有点混乱。基本上,对于两种不同的用途,我需要对同一对象有两种不同的视图。第一个是编辑对象本身,我希望未设置的字段显示为空(未设置)。第二个是针对所有其他情况(包括当对象是另一个对象的字段的值时),其中我想用动态确定的默认值显示每个字段。只是第一次设置默认值并没有帮助,因为如果(在这种情况下)名称字段发生更改,那么Label字段也必须更改,直到设置了Label字段


答案越来越接近,但我仍然认为它们过于针对我给出的例子。我试图为说明目的提供一个具体的例子,但实际上这更像是一个最佳实践问题。我给出的例子是C#和字符串属性,但是我遇到的问题与我使用的大多数语言和系统有相同的框架,其中为您处理数据访问和数据显示以及除字符串以外的数据类型。更改从数据源查询的对象是可能的,但通常很棘手并且知道何时进行更改(在这种情况下使用子类而不是在那个中使用子类)特别困难。

3 个答案:

答案 0 :(得分:1)

public class FooBat {
    public string Name { get; set; }    
    public string Label {
        get {
             if (_label == null) 
                 _label = Name;
             return _label;        
            }        
        set { _label = value; }    
   }
}

关于您的更新: 您可以继承您的对象。如果尚未设置字段并且子类将返回默认值,则基类将返回null。因此,如果您需要查询是否已设置了值,则应转换为基类。

答案 1 :(得分:0)

为简洁起见删除了之前的答案/更新。

<小时/> 更新2: 我不得不说最好的方法是使用IsPropertySet bool跟踪属性是否已设置。属性的Getter将检查该值以查看它是否应返回其自己的值或默认值。并且属性的setter将根据设置值设置IsPropertySet(如果值不为null,则为true,否则为false)。然后,使用该类的代码可以查看IsPropertySet值以确定它是否正在接收设置值,或者在调用Property的Getter时是否为默认值。

public class FooBat {
   public string Name { get; set; }
   public bool IsLabelSet { get; set; }
   public string Label {
      get {
         if (IsLabelSet)
            return _label;
         else
            return Name;
      }
      set {
         IsLabelSet = value != null;
         _label = value;
      }
   }
}

答案 2 :(得分:0)

我经常使用Nameable接口(getName())。在我开始之前,我建议你根本不想这样做。它应该是显示逻辑的域,而不是域对象。通常,消耗FooBat的代码能够以比对象本身更好的方式做出此决策。除此之外......

public interface Label{
    string getLabel();
    boolean isDefault(); //or isValued() or use instanceof expressions
}

public interface Nameable{
    string getName();
}

public class FooBat implements Nameable {
    public string Name { get; set; }
    public Label Label {
        get {
            if (_label == null) {
                _label = new DefaultLabel(this);
            }
            return _label;
        }
        set { _label = value; }
    }
}

public class DefaultLabel implements Label{
    public DefaultCharSequence(Nameable named){
        this.named = named;
    }

    public string getLabel(){
        return named.getName();
    }

    public boolean isDefault(){ return true; }
 }

 public class StringLabel implements Label {
     ...
 }

这一切基本归结为为标签对象返回更好的类。