3

我刚刚在 C# 上发现了这样的问题,并将一些代码转换为 F#,但遗憾的是它仍在返回它的名称。问题是:我的错误在哪里?或者当我想获得 ABToString()

这是我的尝试:

[<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
4

2 回答 2

5

正如罗伯特所提到的,因为枚举不能有成员,因此你不能覆盖ToString,你可以做这样的事情,作为一种妥协:

type FontVariant =
  | ``small-caps`` = 0

然后,printf按需要工作:

printfn "%A" FontVariant.``small-caps``
> 小型股

此外,John 建议使用有区别的工会是一个很好的建议。它们看起来就像枚举,减去数值:

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
于 2013-02-14T16:00:55.340 回答
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

也就是说,如果可用,某些库/框架将使用类型转换器。可能看起来像这样。可能你也必须实现 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)
于 2013-02-14T08:02:28.400 回答