열거형을 사람이 읽을 수 있는 값으로 변환
-
08-06-2019 - |
문제
열거형 값을 사람이 읽을 수 있는 값으로 변환하는 방법을 아는 사람이 있나요?
예를 들어:
ThisIsValueA는 "값 A입니다"여야 합니다.
해결책
특정 Ian Horwill이 남긴 VB 코드 조각에서 이것을 변환합니다. 오래전 블로그 포스팅...나는 이후 이것을 프로덕션에서 성공적으로 사용했습니다.
/// <summary>
/// Add spaces to separate the capitalized words in the string,
/// i.e. insert a space before each uppercase letter that is
/// either preceded by a lowercase letter or followed by a
/// lowercase letter (but not for the first char in string).
/// This keeps groups of uppercase letters - e.g. acronyms - together.
/// </summary>
/// <param name="pascalCaseString">A string in PascalCase</param>
/// <returns></returns>
public static string Wordify(string pascalCaseString)
{
Regex r = new Regex("(?<=[a-z])(?<x>[A-Z])|(?<=.)(?<x>[A-Z])(?=[a-z])");
return r.Replace(pascalCaseString, " ${x}");
}
('System.Text.RegularExpressions 사용' 필요)
따라서:
Console.WriteLine(Wordify(ThisIsValueA.ToString()));
돌아올 것이다,
"This Is Value A".
Description 속성을 제공하는 것보다 훨씬 간단하고 덜 중복됩니다.
여기서 속성은 간접 계층(질문에서 요구하지 않은)을 제공해야 하는 경우에만 유용합니다.
다른 팁
Enums의 .ToString은 C#에서 GetType().Name과 비교할 때 상대적으로 느립니다(내부에서 이를 사용할 수도 있음).
솔루션이 매우 빠르거나 효율적이어야 하는 경우 정적 사전에 변환을 캐시하고 거기에서 검색하는 것이 가장 좋습니다.
C#3을 활용하기 위해 @Leon의 코드를 약간 수정했습니다.이는 열거형의 확장으로서 의미가 있습니다. 모든 항목을 복잡하게 만들고 싶지 않다면 이를 특정 유형으로 제한할 수 있습니다.
public static string Wordify(this Enum input)
{
Regex r = new Regex("(?<=[a-z])(?<x>[A-Z])|(?<=.)(?<x>[A-Z])(?=[a-z])");
return r.Replace( input.ToString() , " ${x}");
}
//then your calling syntax is down to:
MyEnum.ThisIsA.Wordify();
내가 본 대부분의 예에는 열거형 값을 [Description] 속성으로 표시하고 리플렉션을 사용하여 값과 설명 간의 "변환"을 수행하는 것이 포함됩니다.이에 대한 오래된 블로그 게시물은 다음과 같습니다.
http://geekswithblogs.net/rakker/archive/2006/05/19/78952.aspx
System.Reflection의 "속성" 클래스에서 상속하여 고유한 "설명" 클래스를 만들 수 있습니다.이렇게 (부터 여기):
using System;
using System.Reflection;
namespace FunWithEnum
{
enum Coolness : byte
{
[Description("Not so cool")]
NotSoCool = 5,
Cool, // since description same as ToString no attr are used
[Description("Very cool")]
VeryCool = NotSoCool + 7,
[Description("Super cool")]
SuperCool
}
class Description : Attribute
{
public string Text;
public Description(string text)
{
Text = text;
}
}
class Program
{
static string GetDescription(Enum en)
{
Type type = en.GetType();
MemberInfo[] memInfo = type.GetMember(en.ToString());
if (memInfo != null && memInfo.Length > 0)
{
object[] attrs = memInfo[0].GetCustomAttributes(typeof(Description), false);
if (attrs != null && attrs.Length > 0)
return ((Description)attrs[0]).Text;
}
return en.ToString();
}
static void Main(string[] args)
{
Coolness coolType1 = Coolness.Cool;
Coolness coolType2 = Coolness.NotSoCool;
Console.WriteLine(GetDescription(coolType1));
Console.WriteLine(GetDescription(coolType2));
}
}
}
다음 기사를 살펴볼 수도 있습니다. http://www.codeproject.com/KB/cs/enumdatabind.aspx
특히 데이터 바인딩에 관한 것이지만 속성을 사용하여 열거형 값을 장식하는 방법을 보여주고 속성의 텍스트를 검색하는 "GetDescription" 메서드를 제공합니다.내장된 설명 속성을 사용할 때의 문제점은 해당 속성을 다른 용도/사용자가 사용하므로 원하지 않는 위치에 설명이 나타날 가능성이 있다는 것입니다.맞춤 속성이 해당 문제를 해결합니다.
ThisIsValueA가 This_Is_Value_A가 되도록 열거형 값을 아래 점수로 정의하는 것이 가장 좋습니다. 그러면 enumValue가 변수인 enumValue.toString().Replace("_"," ")를 수행할 수 있습니다.
추가의 대안 Description
각 열거형에 대한 속성은 확장 메서드를 만드는 것입니다.Adam의 "Coolness" 열거형을 재사용하려면:
public enum Coolness
{
NotSoCool,
Cool,
VeryCool,
SuperCool
}
public static class CoolnessExtensions
{
public static string ToString(this Coolness coolness)
{
switch (coolness)
{
case Coolness.NotSoCool:
return "Not so cool";
case Coolness.Cool:
return "Cool";
case Coolness.VeryCool:
return "Very cool";
case Coolness.SuperCool:
return Properties.Settings.Default["SuperCoolDescription"].ToString();
default:
throw new ArgumentException("Unknown amount of coolness", nameof(coolness));
}
}
}
이는 설명이 실제 값과 더 멀리 떨어져 있음을 의미하지만 현지화를 사용하여 각 언어에 대해 다른 문자열을 인쇄할 수 있습니다. VeryCool
예.