【问题标题】:Limit property to specific values将属性限制为特定值
【发布时间】:2014-12-26 18:42:06
【问题描述】:

类中的某些属性只有某些值是可接受的。但是,数据库中的相应字段是字符串 (nvarchar) 类型。这意味着该字段可能具有不可接受的值,在这种情况下,应为实际字段分配一个预选值,而不是读取的值。

(此时无法更改数据库的架构或内容。)

我正在尝试找到一种方法来拥有一个可以分配字符串的属性,但如果该字符串不是可接受的字符串之一,则将存储一个预先选择的值。

一种基本可行的方法是使用something that works as a string-based enum 作为内部(私有)字段,并且只公开(设置为公共)遵循此逻辑的属性,如下例所示(在这种情况下,是一个不可接受的值被视为值“Real”):

public class Item
{
    private sealed class Reality
    {
        public readonly string Value;

        private Reality(string value)
        {
            Value = value;
        }

        public static readonly Reality Real = new Reality("Real");
        public static readonly Reality Imaginary = new Reality("Imaginary");
        public static readonly Reality BasedOnReality = new Reality("Based on reality");
    }

    private Reality _realityValue;

    public string RealityStr
    {
        get { return _realityValue.Value; }
        set
        {
            if (value == Reality.Imaginary.Value)
            {
                _realityValue = Reality.Imaginary;
            }
            else if (value == Reality.BasedOnReality.Value)
            {
                _realityValue = Reality.BasedOnReality;
            }
            else
            {
                _realityValue = Reality.Real;
            }
        }
    }
}

以上工作正常:

Item item = new Item();

item.RealityStr = "Real";
Console.WriteLine(item.RealityStr); //Output: Real

item.RealityStr = "Imaginary";
Console.WriteLine(item.RealityStr); //Output: Imaginary

item.RealityStr = "Existing";
Console.WriteLine(item.RealityStr); //Output: Real

这种方法的问题在于,必须为每个字段分别定义这样的类和相应的设置器。理想情况下,逻辑只定义一次,可接受的值列表将在字段定义中给出,如下所示(无效的 C# 语法):

public class Item
{
    public LimitedString<"Real", "Imaginary", "Based on reality"> Reality;

    public LimitedString<"Other", "Blue", "Red", "Green"> Colour;
}

(在这个例子中,LimitedString 是一种类型,它实现了我正在寻找的逻辑,对于给定的字符串列表。默认值是第一个。)

我认为可以使用一个自定义属性来执行此操作,该属性给出了一个字符串列表和一个特殊类,其语法如下所示:

public class Item
{
    [AcceptableValues("Real", "Imaginary", "Based on reality")]
    public LimitedString Reality;

    [AcceptableValues("Other", "Blue", "Red", "Green")]
    public LimitedString Colour;
}

但是我无法找到一种方法让类可以读取应用于自身特定实例的属性,这再次意味着必须为每个具有可接受值的属性复制一些逻辑。 此外,赋值必须由函数完成,因为不可能重载赋值运算符,并且使用 public implicit operator LimitedString(string value) 将返回一个新的 LimitedString 对象,这意味着我再次需要为每个属性使用不同的类。

这在 C# 中是否可以在不为每个特定字段/属性复制逻辑的情况下完成?我希望我已经很好地描述了这个问题。

【问题讨论】:

  • 有什么原因你没有在这里使用 actual 枚举?
  • 为什么不使用枚举呢?
  • 我以为我在一开始就描述了这一点(除非我的大脑太煎熬而且我遗漏了一些明显的东西):检查每个字符串对应的枚举值并决定默认值的代码,如果给定的字符串是不可接受的,必须为每个属性复制。
  • 为每个枚举值返回适当字符串的代码也会如此,以在显示数据时使用。
  • 您需要在字符串上使用Enum.TryParse,如果函数返回false,请将值设置为您想要的任何默认值。

标签: c# .net custom-attributes


【解决方案1】:

我想不可能像我想象的那样在一行中完成。

我将采用以下方法,我认为这是尽可能减少代码重复的方法:

public class Item
{
    private readonly LimitedString _reality = new LimitedString("Real", 
        "Imaginary", "Based on reality");
    public string Reality
    {
        get { return _reality.Value; }
        set { _reality.Value = value; }
    }

    private readonly LimitedString _colour = new LimitedString("Other", 
        "Blue", "Red", "Green");
    public string Colour
    {
        get { return _colour.Value; }
        set { _colour.Value = value; }
    }
}

C++ 风格的宏在这里可能会很有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多