将属性限制为特定值

时间:2014-10-30 16:03:02

标签: c# .net custom-attributes

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

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

我正在试图想出一种方法来获得一个可以分配字符串的属性,但是,如果该字符串不是可接受的字符串之一,则会存储预先选择的值。

一种基本上有效的方法是使用something that works as a string-based enum作为内部(私有)字段,并且只显示(设置为public)一个遵循此逻辑的属性,如下例所示(在本例中为不可接受的价值被视为“真实”的价值):

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

这种方法的问题是必须分别为每个字段定义这样的类和相应的setter。理想情况下,逻辑只定义一次,可接受值的列表将在字段的定义中给出,如下所示(无效的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对象,这意味着我再次需要为每个属性使用不同的类。 / p>

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

1 个答案:

答案 0 :(得分: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 ++风格的宏在这里很有用。