我刚刚在C#上发现了这样的问题,并将一些代码转换为F#,但遗憾的是它仍在返回它的名字。问题是:我的错误在哪里?或者当我想要获得A.B.ToString()
时,是否有其他方法可以使用可选的字符串returnin来获得类似枚举的结构这是我的尝试:
[<TypeConverter(typedefof<EnumToStringUsingDescription>)>]
type FontVariant =
| [<Description("small-caps")>] smallCaps = 0
和
type EnumToStringUsingDescription() =
inherit TypeConverter()
override X.CanConvertFrom(context : ITypeDescriptorContext, sourceType : Type) =
sourceType.Equals(typedefof<Enum>);
override X.CanConvertTo(context : ITypeDescriptorContext, destinationType : Type) =
(destinationType.Equals(typedefof<String>));
override X.ConvertFrom(context : ITypeDescriptorContext, culture : System.Globalization.CultureInfo, value : obj) =
base.ConvertFrom(context, culture, value);
override X.ConvertTo(context : ITypeDescriptorContext, culture : System.Globalization.CultureInfo, value : obj, destinationType : Type) =
if (not <| destinationType.Equals(typedefof<String>)) then
raise <| new ArgumentException("Can only convert to string.", "destinationType");
if (not <| value.GetType().BaseType.Equals(typedefof<Enum>)) then
raise <| new ArgumentException("Can only convert an instance of enum.", "value");
let name = value.ToString();
let attrs =
value.GetType().GetField(name).GetCustomAttributes(typedefof<DescriptionAttribute>, false);
if (attrs.Length > 0) then attrs.[0]
else value
答案 0 :(得分:5)
这里有几个问题。首先,添加TypeConverter不会影响.ToString()
。
其次,您的转换返回属性,而不是属性中的描述。这是一个有效的功能。
let getEnumDescription (value: Enum) =
let typ = value.GetType()
let name = value.ToString();
let attrs = typ.GetField(name).GetCustomAttributes(typedefof<DescriptionAttribute>, false)
if (attrs.Length > 0) then (attrs.[0] :?> DescriptionAttribute).Description :> obj
else name :> obj
也就是说,某些库/框架将使用Type转换器(如果可用)。可能看起来像这样。可能你必须实现ConvertFrom / CanConvertFrom,我不确定。
type EnumToStringUsingDescription() =
inherit TypeConverter()
override X.CanConvertTo(context : ITypeDescriptorContext, destinationType : Type) = (destinationType.Equals(typedefof<String>))
override X.ConvertTo(context : ITypeDescriptorContext, culture : System.Globalization.CultureInfo, value : obj, destinationType : Type) =
let typ = value.GetType()
if (not <| typ.IsEnum) then raise <| new ArgumentException("Can only convert from enum.", "value");
if (not <| typ.Equals typeof<string>) then raise <| new ArgumentException("Can only convert to string.", "destinationType");
getEnumDescription (value :?> Enum)
答案 1 :(得分:5)
正如罗伯特所提到的,因为枚举不能拥有成员,因此你无法覆盖ToString
,你可以做这样的事情,作为一种妥协:
type FontVariant =
| ``small-caps`` = 0
然后,printf
按预期工作:
printfn "%A" FontVariant.``small-caps``
> small-caps
此外,约翰建议使用受歧视的联盟是一个很好的建议。它们看起来就像枚举,减去数值:
type FontVariant =
| SmallCaps
override this.ToString() =
match this with
| SmallCaps -> "small-caps"
使用%O
格式(%A
将使用反射并打印案例名称。)
printfn "%O" FontVariant.SmallCaps
如果您需要数字值,就像枚举提供的那样,您可以定义属性:
member this.Value =
match this with
| SmallCaps -> 0
printfn "%d" FontVariant.SmallCaps.Value