【发布时间】: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