根据List中的其他项阻止属性更改

时间:2014-04-16 15:25:40

标签: c# list validation

我正在尝试创建一个对象列表,每个对象都有一个可以由程序或用户更改的Name成员,我想阻止对象的Name更改为列表中已存在的名称

示例:

Class Recipe {
  Public String Name {get; set;}
  Public int difficulty_level {get; set;}
  Public List<string> Ingredients = new List<string>();
  Public Recipe (string name) {Name = name;}
}

Class RecipeBook {
  Public List<Recipe> RecipeList = new List<Recipe>();
  Public AddRecipe {RecipeList.Add (AssignUniqueName());}
  Public RecipeBook() { }
}

添加配方时,它在列表级别完成,因此很容易为其分配唯一的名称。用户可以使用UI中的PropertyGrid控件来编辑配方对象。如果用户试图将Name属性更改为另一个配方的名称,我希望PropertyGrid阻止它(就像我们在数字字段中键入文本一样)。理想情况下,Name属性不会更改。如果那是不可能的,那么它将会改变,验证将失败并且更改将被恢复。

由于每个Recipe对象只知道自身并且不知道其他配方,我怎样才能阻止用户将Recipe对象的名称更改为存在的名称?

以下是我考虑的方法:

  1. 使用TypeConverter进行验证。似乎TypeConverter是验证的正确工具,因此这将是首选方法。问题:我需要一个现有的验证名称列表,我不能将任何参数传递给TypeConverter。
  2. 实施INotifyChangedProperty。 Recipe对象将使用事件通知更改,发送旧值和新值,列表将侦听事件,验证并在需要时还原更改。它可能会奏效,但我希望有一个更优雅的解决方案。我也不知道如何在PropertyGrid中将其反映为错误消息。
  3. 的ObservableCollection。它只观察添加/删除项目。没有更改这些项目。
  4. 在Recipe中包含RecipeList中的引用,并使用setter验证更改并在验证失败时抛出异常。可能会工作,我觉得它不是一个好的设计。
  5. 奖金问题:有没有办法确保食谱只会添加到一个食谱?意思是,只有一个List会指向/引用任何Recipe对象吗?

    非常感谢你!

3 个答案:

答案 0 :(得分:1)

最好的选择是阻止用户直接创建Recipe个对象,而不是强迫他们浏览食谱,以便创建新的食谱。如果Recipe对象是不可变的,而不是不可变的,那么它也将更容易使用。处理食谱变异,并仍然保持这种约束,将是一场噩梦。这可以通过使Recipe成为RecipeBook的内部类,而不是公开公开,并且具有的接口来公开应该公开显示的内容来完成。

public interface IRecipe
{
    public string Name { get; }
    public IEnumerable<string> Ingredients { get; }
    public int Difficulty { get; }
}
public class RecipeBook
{
    private List<Recipe> recipes = new List<Recipe>();

    public IRecipe AddRecipe(string name, IEnumerable<string> ingredients,
        int difficulty)
    {
        if (recipes.Any(recipe => recipe.Name == name))
            throw new ArgumentException("Recipe name already exists");
        var result = new Recipe(name, ingredients, difficulty);
        recipes.Add(result);
        return result;
    }

    private class Recipe : IRecipe
    {
        public Recipe(string name, IEnumerable<string> ingredients,
            int difficulty)
        {
            Name = name;
            Ingredients = ingredients.ToList();
            Difficulty = difficulty;
        }

        public string Name { get; private set; }
        public IEnumerable<string> Ingredients { get; private set; }
        public int Difficulty { get; private set; }
    }
}

答案 1 :(得分:0)

无法确定您希望如何获得唯一名称

Public bool AddRecipe(string TheUsersSpecifiedName)
{
bool noDuplicates = true;
foreach (Recipe r in RecipeList)
{
if (r.Name == TheUserSpecifiedName)
throw new ArgumentException();  //or whatever...
noDuplicates = false;
break;
}
if (noDuplicates)
{
Recipe theRecipe = new Recipe(TheUserSpecifiedName)
RecipeList.Add(theRecipe);
}

return noDuplicates;
}

我知道有些人会不同意抛出一个Argument异常,但你明白了。希望这就是你所追求的。

答案 2 :(得分:0)

在食谱类

中创建静态名称列表
Class Recipe {
  private static List<string> names=new List<string>();
   private string name;
 Public String Name {get{return name;}
 set{
foreach(string nam in names) 
{
if(nam==value)//tell the user to try another name
else{  name=value;names.Add(name);}
}

}
}

  Public int difficulty_level {get; set;}
  Public List<string> Ingredients = new List<string>();
  Public Recipe (string name) {Name = name;}
}

Class RecipeBook {
  Public List<Recipe> RecipeList = new List<Recipe>();
  Public AddRecipe {RecipeList.Add (AssignUniqueName());}
  Public RecipeBook() { }
}
相关问题