3

私はちょうどC#でそのような質問を見つけ、いくつかのコードをF#に変換しましたが、残念ながらそれはまだその名前を返しています。問題は、私の間違いはどこにあるのかということです。または、ABToString()を取得したいときに、オプションの文字列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
4

2 に答える 2

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 に答える
5

Robertが述べたように、列挙型はメンバーを持つことができず、したがってオーバーライドできないためToString、一種の妥協案として、次のようなことを行うことができます。

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

次に、printf必要に応じて動作します。

printfn "%A" FontVariant.``small-caps``
>スモールキャップス

また、識別された共用体を使用するというジョンの提案は良いものです。列挙型から数値を除いたものと同じように見えます。

type FontVariant =
  | SmallCaps
  override this.ToString() =
    match this with
    | SmallCaps -> "small-caps"

フォーマットを使用し%Oます(%AReflectionを使用し、ケース名を出力します)。

printfn "%O" FontVariant.SmallCaps

列挙型が提供するように、数値が必要な場合は、プロパティを定義できます。

member this.Value =
  match this with
  | SmallCaps -> 0

printfn "%d" FontVariant.SmallCaps.Value
于 2013-02-14T16:00:55.340 に答える