source

C#의 문자열과 열거형 연결

lovecheck 2023. 5. 12. 22:23
반응형

C#의 문자열과 열거형 연결

Enumeration 유형이 int여야 하므로 다음이 불가능하다는 것을 알고 있습니다.

enum GroupTypes
{
    TheGroup = "OEM",
    TheOtherGroup = "CMB"
}

이지 않은 있는 .OEM그리고.CMB저는 이 분야를 하나로 만들고 싶습니다.enum또것이수할있 는▁because것. 왜냐하면이 더입니다.왜냐하면 가독성이 목표라면 해결책이 까다로워야 하기 때문입니다.

다른 선택지는 무엇입니까?

클래스에서 메소드 대신 속성을 사용하는 것이 좋습니다. 속성이 더 열거형처럼 보이기 때문입니다.

다음은 로거의 예입니다.

public class LogCategory
{
    private LogCategory(string value) { Value = value; }

    public string Value { get; private set; }

    public static LogCategory Trace   { get { return new LogCategory("Trace"); } }
    public static LogCategory Debug   { get { return new LogCategory("Debug"); } }
    public static LogCategory Info    { get { return new LogCategory("Info"); } }
    public static LogCategory Warning { get { return new LogCategory("Warning"); } }
    public static LogCategory Error   { get { return new LogCategory("Error"); } }

    public override string ToString()
    {
        return Value;
    }
}

type-safe 문자열 값을 매개 변수로 전달:

public static void Write(string message, LogCategory logCategory)
{
    var log = new LogEntry { Message = message };
    Logger.Write(log, logCategory.Value);
}

용도:

Logger.Write("This is almost like an enum.", LogCategory.Info);

확장 모델을 사용할 수도 있습니다.

public enum MyEnum
{
    [Description("String 1")]
    V1= 1,
    [Description("String 2")]
    V2= 2
} 

확장 클래스

public static class MyEnumExtensions
{
    public static string ToDescriptionString(this MyEnum val)
    {
        DescriptionAttribute[] attributes = (DescriptionAttribute[])val
           .GetType()
           .GetField(val.ToString())
           .GetCustomAttributes(typeof(DescriptionAttribute), false);
        return attributes.Length > 0 ? attributes[0].Description : string.Empty;
    }
} 

용도:

MyEnum myLocal = MyEnum.V1;
print(myLocal.ToDescriptionString());

상수가 있는 정적 클래스를 사용하는 것은 어떻습니까?

static class GroupTypes
{
  public const string TheGroup = "OEM";
  public const string TheOtherGroup = "CMB";
}

void DoSomething(string groupType)
{
  if(groupType == GroupTypes.TheGroup)
  {
    // Be nice
  }  
  else if (groupType == GroupTypes.TheOtherGroup)
  {
    // Continue to be nice
  }
  else
  {
    // unexpected, throw exception?
  }
}

저는 이전 답변에서 언급한 구조를 사용했지만, 복잡성을 제거했습니다.저에게 이것은 문자열의 열거형을 만드는 것과 같았습니다.이것은 열거형이 사용되는 것과 같은 방식으로 사용됩니다.

    struct ViewTypes
    {
        public const string View1 = "Whatever string you like";
        public const string View2 = "another string";
    }

사용 예:

   switch( some_string_variable )
   {
      case ViewTypes.View1: /* do something */ break;
      case ViewTypes.View2: /* do something else */ break;
   }

정적 클래스에 상수를 추가해 보십시오.유형이 표시되는 것은 아니지만 읽기 쉽고 정리된 상수가 표시됩니다.

public static class GroupTypes {

    public const string TheGroup = "OEM";
    public const string TheOtherGroup = "CMB";

}

실제로 매우 쉽게 할 수 있습니다.다음 코드를 사용합니다.

enum GroupTypes
{
   OEM,
   CMB
};

그런 다음 각 열거 요소의 문자열 값을 가져오려면 다음 코드 행을 사용하십시오.

String oemString = Enum.GetName(typeof(GroupTypes), GroupTypes.OEM);

저는 과거에 이 방법을 성공적으로 사용했고, 또한 문자열 상수를 유지하기 위해 상수 클래스를 사용했습니다. 둘 다 꽤 잘 작동하지만, 저는 이것을 선호하는 경향이 있습니다.

열거형의 항목에 속성을 추가한 다음 반사를 사용하여 속성에서 값을 가져올 수 있습니다.

다음과 같이 "필드" 지정자를 사용하여 속성을 적용해야 합니다.

enum GroupTypes
{
    [field:Description("OEM")]
    TheGroup,

    [field:Description("CMB")]
    TheOtherGroup
}

그런 다음 열거형 유형(이 경우 GroupTypes)의 정적 필드를 반영하고 반사를 사용하여 찾고 있던 값을 가져옵니다.

public static DescriptionAttribute GetEnumDescriptionAttribute<T>(
    this T value) where T : struct
{
    // The type of the enum, it will be reused.
    Type type = typeof(T);

    // If T is not an enum, get out.
    if (!type.IsEnum) 
        throw new InvalidOperationException(
            "The type parameter T must be an enum type.");

    // If the value isn't defined throw an exception.
    if (!Enum.IsDefined(type, value))
        throw new InvalidEnumArgumentException(
            "value", Convert.ToInt32(value), type);

    // Get the static field for the value.
    FieldInfo fi = type.GetField(value.ToString(), 
        BindingFlags.Static | BindingFlags.Public);

    // Get the description attribute, if there is one.
    return fi.GetCustomAttributes(typeof(DescriptionAttribute), true).
        Cast<DescriptionAttribute>().SingleOrDefault();
}

나는 그것을 돌려주기로 선택했습니다.DescriptionAttribute속성이 적용되는지 여부를 결정할 수 있는 경우 위의 자체입니다.

클래스를 사용합니다.

편집: 더 나은 예

class StarshipType
{
    private string _Name;
    private static List<StarshipType> _StarshipTypes = new List<StarshipType>();

    public static readonly StarshipType Ultralight = new StarshipType("Ultralight");
    public static readonly StarshipType Light = new StarshipType("Light");
    public static readonly StarshipType Mediumweight = new StarshipType("Mediumweight");
    public static readonly StarshipType Heavy = new StarshipType("Heavy");
    public static readonly StarshipType Superheavy = new StarshipType("Superheavy");

    public string Name
    {
        get { return _Name; }
        private set { _Name = value; }
    }

    public static IList<StarshipType> StarshipTypes
    {
        get { return _StarshipTypes; }
    }

    private StarshipType(string name, int systemRatio)
    {
        Name = name;
        _StarshipTypes.Add(this);
    }

    public static StarshipType Parse(string toParse)
    {
        foreach (StarshipType s in StarshipTypes)
        {
            if (toParse == s.Name)
                return s;
        }
        throw new FormatException("Could not parse string.");
    }
}

다음을 포함하는 DB에 대한 두 번째 열거형을 작성합니다.

enum DBGroupTypes
{
    OEM = 0,
    CMB = 1
}

이제 Enum을 사용할 수 있습니다.구문 분석하여 "OEM" 및 "CMB" 문자열에서 올바른 DBGroupTypes 값을 검색합니다.그런 다음 이러한 값을 int로 변환하고 모델에서 추가로 사용할 올바른 열거형에서 올바른 값을 검색할 수 있습니다.

이 문제를 해결하는 또 다른 방법은 열거형 및 문자열 목록과 열거형 값을 매핑할 문자열 배열을 갖는 것입니다.

public enum GroupTypes
{
    TheGroup  = 0,
    TheOtherGroup 
}

string[] GroupTypesStr = {
    "OEM",
    "CMB"
};

다음과 같은 방법으로 사용할 수 있습니다.

Log.Write(GroupTypesStr[(int)GroupTypes.TheOtherGroup]);

CMB 메시지가 표시됩니다.

장점:

  1. 간편하고 깨끗한 코드.
  2. 고성능(특히 클래스를 사용하는 접근 방식과 비교하여)

단점:

  1. 목록을 편집할 때 목록을 엉망으로 만드는 경향이 있지만, 짧은 목록은 괜찮습니다.

다음은 열거값을 문자열로 가져오는 데 사용한 확장 메서드입니다.첫 번째는 열거형입니다.

public enum DatabaseEnvironment
{
    [Description("AzamSharpBlogDevDatabase")]
    Development = 1, 
    [Description("AzamSharpBlogQADatabase")]
    QualityAssurance = 2, 
    [Description("AzamSharpBlogTestDatabase")] 
    Test = 3
}

Description 특성이 System에서 왔습니다.구성요소 모델.

다음은 제 확장 방법입니다.

public static string GetValueAsString(this DatabaseEnvironment environment) 
{
    // get the field 
    var field = environment.GetType().GetField(environment.ToString());
    var customAttributes = field.GetCustomAttributes(typeof (DescriptionAttribute), false);

    if(customAttributes.Length > 0)
    {
        return (customAttributes[0] as DescriptionAttribute).Description;  
    }
    else
    {
        return environment.ToString(); 
    }
}

이제 다음 코드를 사용하여 열거형을 문자열 값으로 액세스할 수 있습니다.

[TestFixture]
public class when_getting_value_of_enum
{
    [Test]
    public void should_get_the_value_as_string()
    {
        Assert.AreEqual("AzamSharpBlogTestDatabase",DatabaseEnvironment.Test.GetValueAsString());  
    }
}

새로운 기능.NetCore 3.0/C# 8.0(작업 환경에서 프로젝트를 업그레이드할 수 있는 경우)은 다소 열거형으로 보이는 간단한 스위치 문입니다.결국, 이것은 우리가 수년간 사용해 온 지루한 스위치 문구입니다.

여기서 유일한 차이점은 스위치 문구가 새 양복을 받았다는 것입니다.

public static RGBColor FromRainbow(Rainbow colorBand) =>
colorBand switch
{
    Rainbow.Red    => new RGBColor(0xFF, 0x00, 0x00),
    Rainbow.Orange => new RGBColor(0xFF, 0x7F, 0x00),
    Rainbow.Yellow => new RGBColor(0xFF, 0xFF, 0x00),
    Rainbow.Green  => new RGBColor(0x00, 0xFF, 0x00),
    Rainbow.Blue   => new RGBColor(0x00, 0x00, 0xFF),
    Rainbow.Indigo => new RGBColor(0x4B, 0x00, 0x82),
    Rainbow.Violet => new RGBColor(0x94, 0x00, 0xD3),
    _              => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)),
};

여기서 복사한 위의 코드는 실제로 열거형을 매개변수로 사용하고 있습니다.

정확히 당신이 원하는 것은 아니지만(그리고 저를 믿으세요, 저는 오랫동안 OP가 요청하는 것과 비슷한 것을 원했습니다), 하지만 저는 사실 이것이 MS. JMO의 올리브 가지처럼 느껴집니다.

누군가에게 도움이 되길 바랍니다!

동일한 열거형을 사용하지 않고 전화만 하는 이유는 무엇입니까?.ToString()?

using System;

public class EnumSample
{
    enum Holidays
    {
        Christmas = 1,
        Easter = 2
    };

    public static void Main()
    {
        Enum myHolidays = Holidays.Christmas;
        Console.WriteLine("The value of this instance is '{0}'", myHolidays.ToString());
    }
}

@EvenMien에서 발췌하여 일부 댓글에 추가하였습니다. (나만의 사용 사례에 대해서도)

public struct AgentAction
{
    private AgentAction(string value) { Value = value; }

    public string Value { get; private set; }

    public override string ToString() { return this.Value; }
    
    public static AgentAction Login = new AgentAction("Login");
    public static AgentAction Logout = new AgentAction("Logout");

    public static implicit operator string(AgentAction action) { return action.ToString(); }
}

사전을 사용한 조회 테이블을 고려해 보셨습니까?

enum GroupTypes
{
    TheGroup,
    TheOtherGroup
}

Dictionary<string, GroupTypes> GroupTypeLookup = new Dictionary<string, GroupTypes>();
// initialize lookup table:
GroupTypeLookup.Add("OEM", TheGroup);
GroupTypeLookup.Add("CMB", TheOtherGroup);

그런 다음 GroupTypeLookup을 사용할 수 있습니다.GetValue()를 사용하여 문자열을 읽을 때 해당 문자열을 검색합니다.

저는 단지 사전을 만들고 코드를 키로 사용할 것입니다.

편집: 역방향 조회(키 찾기)를 수행하는 것에 대한 의견을 처리하는 것은 그다지 효율적이지 않습니다.만약 이것이 필요하다면, 저는 그것을 다루기 위해 새로운 수업을 쓸 것입니다.

public class DataType
{
    private readonly string value;
    private static readonly Dictionary<string, DataType> predefinedValues;

    public static readonly DataType Json = new DataType("json");
    public static readonly DataType Xml = new DataType("xml");
    public static readonly DataType Text = new DataType("text");
    public static readonly DataType Html = new DataType("html");
    public static readonly DataType Binary = new DataType("binary");

    static DataType()
    {
        predefinedValues = new Dictionary<string, DataType>();
        predefinedValues.Add(Json.Value, Json);
        predefinedValues.Add(Xml.Value, Xml);
        predefinedValues.Add(Text.Value, Text);
        predefinedValues.Add(Html.Value, Html);
        predefinedValues.Add(Binary.Value, Binary);
    }

    private DataType(string value)
    {
        this.value = value;
    }

    public static DataType Parse(string value)
    {
        var exception = new FormatException($"Invalid value for type {nameof(DataType)}");
        if (string.IsNullOrEmpty(value))
            throw exception;

        string key = value.ToLower();
        if (!predefinedValues.ContainsKey(key))
            throw exception;

        return predefinedValues[key];
    }

    public string Value
    {
        get { return value; }
    }
}

다음은 C# 9.0 구문을 사용하여 깨끗하게 유지하는 것에 대한 저의 견해입니다.열거형에 대한 기본 클래스를 정의합니다.

public class StringEnum
{
    protected StringEnum(string value) { Value = value; }
    public string Value { get; }
    public override string ToString() => Value;
}

그러면 새 열거형 스타일 유형을 쉽게 만들 수 있습니다.

public class GroupTypes : StringEnum
{ 
    private GroupTypes(string value) : base(value) {}

    public static readonly GroupTypes TheGroup = new("OEM");
    public static readonly GroupTypes TheOtherGroup = new("CMB");
}

다음과 같이 사용합니다.

void Example(GroupTypes groupType)
{
    Console.WriteLine(groupType); // Will print "OEM" or "CMB"
    if (groupType == GroupTypes.TheGroup) { ... }
}

다음에 더 많은 기능을 추가할 수도 있습니다.StringEnum에서 사용할 수 구현 " " " " " " " " " " " " " " " " " " " " " " " " ).IComparable 및우위순선iding를 재정의함Equals그리고.GetHashCode)

첫 번째 질문 - 데이터베이스 자체에 대한 액세스 권한이 있습니까?데이터베이스에서 이를 표준화해야 합니다. 그렇지 않으면 솔루션에 오류가 발생하기 쉽습니다.제 경험에 따르면, "OEM"과 "CMB"로 가득 찬 데이터 필드는 시간이 지남에 따라 "OEM"과 다른 "크래프 데이터"와 같은 것들이 혼합되는 경향이 있습니다.이를 정규화할 수 있다면 요소가 들어 있는 표의 키를 Enum으로 사용할 수 있습니다. 그러면 훨씬 더 깨끗한 구조로 작업이 완료됩니다.

사용할 수 없으면 Enum을 만들고 문자열을 Enum으로 구문 분석할 클래스를 만듭니다.이렇게 하면 적어도 Enum을 사용하여 해결하는 것보다 비표준 항목을 어느 정도 유연하게 처리할 수 있고 트랩 또는 오류를 처리할 수 있습니다.구문 분석/반영 등.사전은 작동하지만 사례 문제 등이 발생할 경우 고장이 날 수 있습니다.

다음 작업을 수행할 수 있도록 수업을 작성하는 것이 좋습니다.

// I renamed this to GroupType, since it sounds like each element has a single type...
GroupType theType = GroupTypeParser.GetGroupType(theDBString);

이렇게 하면 DB를 변경할 필요 없이 대부분의 가독성이 유지됩니다.

C#은 열거된 문자열을 지원하지 않지만 대부분의 경우 목록 또는 사전을 사용하여 원하는 효과를 얻을 수 있습니다.

예: 합격/불합격 결과 인쇄하기

List<string> PassFail = new List<string> { "FAIL", "PASS" };
bool result = true;
Console.WriteLine("Test1: " + PassFail[result.GetHashCode()]);

다음은 강력한 형식의 매개 변수 또는 문자열로 사용하는 방법입니다.

public class ClassLikeEnum
{
    public string Value
    {
        get;
        private set;
    }

    ClassLikeEnum(string value) 
    {
        Value = value;
    }

    public static implicit operator string(ClassLikeEnum c)
    {
        return c.Value;
    }

    public static readonly ClassLikeEnum C1 = new ClassLikeEnum("RandomString1");
    public static readonly ClassLikeEnum C2 = new ClassLikeEnum("RandomString2");
}

Glennular Extension 메서드에 대한 작은 수정으로 ENUM 이외의 다른 항목에도 확장을 사용할 수 있습니다.

using System;
using System.ComponentModel;
namespace Extensions {
    public static class T_Extensions {
        /// <summary>
        /// Gets the Description Attribute Value
        /// </summary>
        /// <typeparam name="T">Entity Type</typeparam>
        /// <param name="val">Variable</param>
        /// <returns>The value of the Description Attribute or an Empty String</returns>
        public static string Description<T>(this T t) {
            DescriptionAttribute[] attributes = (DescriptionAttribute[])t.GetType().GetField(t.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
            return attributes.Length > 0 ? attributes[0].Description : string.Empty;
        }
    }
}

또는 Linkq 사용

using System;
using System.ComponentModel;
using System.Linq;

namespace Extensions {


public static class T_Extensions {
        public static string Description<T>(this T t) =>
            ((DescriptionAttribute[])t
            ?.GetType()
            ?.GetField(t?.ToString())
            ?.GetCustomAttributes(typeof(DescriptionAttribute), false))
            ?.Select(a => a?.Description)
            ?.FirstOrDefault() 
            ?? string.Empty;  
    }
}

@Even Mien의 대답에 따라 조금 더 나아가서 제네릭으로 만들려고 노력했지만, 거의 다 된 것처럼 보이지만 한 사례는 여전히 저항하고 있으며 아마도 코드를 조금 단순화할 수 있을 것입니다.
수 수할 수 있는 방법을 사람이 .

지금까지 저는 다음과 같은 결과를 얻었습니다.

        Console.WriteLine(TestEnum.Test1);//displays "TEST1"

        bool test = "TEST1" == TestEnum.Test1; //true

        var test2 = TestEnum.Test1; //is TestEnum and has value

        string test3 = TestEnum.Test1; //test3 = "TEST1"

        var test4 = TestEnum.Test1 == TestEnum.Test2; //false
         EnumType<TestEnum> test5 = "TEST1"; //works fine

        //TestEnum test5 = "string"; DOESN'T compile .... :(:(

마법이 일어나는 곳:

public abstract  class EnumType<T>  where T : EnumType<T>   
{

    public  string Value { get; set; }

    protected EnumType(string value)
    {
        Value = value;
    }


    public static implicit operator EnumType<T>(string s)
    {
        if (All.Any(dt => dt.Value == s))
        {
            Type t = typeof(T);

            ConstructorInfo ci = t.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic,null, new Type[] { typeof(string) }, null);

            return (T)ci.Invoke(new object[] {s});
        }
        else
        {
            return null;
        }
    }

    public static implicit operator string(EnumType<T> dt)
    {
        return dt?.Value;
    }


    public static bool operator ==(EnumType<T> ct1, EnumType<T> ct2)
    {
        return (string)ct1 == (string)ct2;
    }

    public static bool operator !=(EnumType<T> ct1, EnumType<T> ct2)
    {
        return !(ct1 == ct2);
    }


    public override bool Equals(object obj)
    {
        try
        {
            return (string)obj == Value;
        }
        catch
        {
            return false;
        }
    }

    public override int GetHashCode()
    {
        return Value.GetHashCode();
    }

    public static IEnumerable<T> All
     => typeof(T).GetProperties()
       .Where(p => p.PropertyType == typeof(T))
       .Select(x => (T)x.GetValue(null, null));



}

나는 그때서야 내 열거에 대해 이것을 선언해야 합니다.

public class TestEnum : EnumType<TestEnum> 
{

    private TestEnum(string value) : base(value)
    {}

    public static TestEnum Test1 { get { return new TestEnum("TEST1"); } }
    public static TestEnum Test2 { get { return new TestEnum("TEST2"); } }
}

저는 그것을 완전히 열거를 피하기 위해 클래스로 만들 것입니다.그런 다음 유형 핸들러를 사용하여 DB에서 객체를 가져올 때 객체를 만들 수 있습니다.

IE:

public class Group
{
    public string Value{ get; set; }
    public Group( string value ){ Value = value; } 
    public static Group TheGroup() { return new Group("OEM"); }
    public static Group OtherGroup() { return new Group("CMB"); }

}

내가 제대로 이해했다면 문자열에서 열거형으로 변환해야 합니다.

enum GroupTypes {
    Unknown = 0,
    OEM = 1,
    CMB = 2
}
static GroupTypes StrToEnum(string str){
    GroupTypes g = GroupTypes.Unknown;
    try {
        object o = Enum.Parse(typeof(GroupTypes), str, true);
        g = (GroupTypes)(o ?? 0);
    } catch {
    }
    return g;
}
// then use it like this
GroupTypes g1 = StrToEnum("OEM");
GroupTypes g2 = StrToEnum("bad value");

원하는 경우 열거형의 제네릭으로 더 화려하게 만들 수 있습니다.

VS 2015에서는 다음 이름을 사용할 수 있습니다.

public class LogCategory
{
    public static string Trace;
    public static string Debug;
    public static string Info;
    public static string Warning;
    public static string Error;
}

용도:

Logger.Write("This is almost like an enum.", nameof(LogCategory.Info));

문자열 리터럴을 완전히 사용하는 것을 피하고 싶었고 항목 설명에 공백이 필요하지 않았습니다.더 중요한 것은 제공된 문자열이 유효한 항목인지 확인할 수 있는 메커니즘을 갖고 싶어서 다음과 같은 해결책을 생각해 냈습니다.

public class Seasons
{
    public static string Spring { get; }
    public static string Summer { get; }
    public static string Fall { get; }
    public static string Winter { get; }

    public static bool IsValid(string propertyName)
    {
        if (string.IsNullOrEmpty(propertyName))
        {
            return false;
        }

        try
        {           
            return typeof(Seasons).GetProperty(propertyName) != null;
        }
        catch
        {
            return false;
        }       
    }
}

작동 방식은 다음과 같습니다.

void Main()
{
    string s = nameof(Seasons.Fall);
    Console.WriteLine($"Fall is valid: {Seasons.IsValid(s)}"); // true

    s = "WrongSeason";
    Console.WriteLine($"WrongSeason is valid: {Seasons.IsValid(s)}"); // false
}

IsValid()를 기본 클래스로 리팩터링하고 반사를 사용하여 유형(MethodBase)을 읽으려고 했습니다.GetCurrentMethod().선언 유형), 그러나 정적으로 유지하기를 원했기 때문에 상속된 유형이 아닌 기본 클래스 유형을 반환합니다.이것에 대한 당신의 치료법은 매우 환영받을 것입니다!제가 달성하고자 했던 것은 다음과 같습니다.

public  class Seasons : ConstantStringsBase
{
    // ... same
}

public  class ConstantStringsBase
{
    public static bool IsValid(string propertyName)
    {       
        return MethodBase.GetCurrentMethod().DeclaringType.GetProperty(propertyName) != null;
    }
}

다른 의견들을 바탕으로, 이것이 제가 생각해낸 것입니다.이렇게 하면 입력할 필요가 없습니다.상수 값을 가져올 값입니다.

다음과 같은 모든 문자열 열거형에 대한 기본 클래스가 있습니다.

using System;
using Newtonsoft.Json;

[JsonConverter(typeof(ConstantConverter))]
public class StringEnum: IConvertible
{
    public string Value { get; set; }

    protected StringEnum(string value)
    {
        Value = value;
    }

    public static implicit operator string(StringEnum c)
    {
        return c.Value;
    }
    public string ToString(IFormatProvider provider)
    {
        return Value;
    }

    public TypeCode GetTypeCode()
    {
        throw new NotImplementedException();
    }

    public bool ToBoolean(IFormatProvider provider)
    {
        throw new NotImplementedException();
    }
    //The same for all the rest of IConvertible methods
}

Json 컨버터는 다음과 같습니다.

using System;
using Newtonsoft.Json;

class ConstantConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (value == null)
        {
            serializer.Serialize(writer, null);
        }
        else
        {
            serializer.Serialize(writer, value.ToString());
        }
    }
}

실제 문자열 열거형은 다음과 같습니다.

public sealed class Colors : StringEnum
{
    public static Colors Red { get { return new Catalog("Red"); } }
    public static Colors Yellow { get { return new Catalog("Yellow"); } }
    public static Colors White { get { return new Catalog("White"); } }

    private Colors(string value) : base(value) { }
}

그리고 이것으로, 여러분은 그냥 Color를 사용할 수 있습니다.Value 속성을 사용하지 않고 json에 직렬화할 수 있는 빨간색

심지어 @Even이 제안한 대로 몇 개의 열거형을 구현했습니다(via).class X그리고.public static X 멤버들), 단지 그것을 나중에 알기 위해, 요즘 시작합니다.넷 4.5, 올바른ToString() 방법이 있습니다.

이제 모든 것을 다시 열거형으로 재구현합니다.

두 개의 열거형을 사용할 수 있습니다.하나는 데이터베이스용이고 다른 하나는 가독성용입니다.

당신은 단지 그들이 동기화를 유지하도록 하기만 하면 되는데, 이것은 적은 비용처럼 보입니다.값을 설정할 필요 없이 위치만 동일하게 설정하면 되지만 값을 설정하면 두 개의 열거형이 관련되어 있음이 매우 명확해지고 오류로 인해 열거형 멤버가 재정렬되지 않습니다.또한 유지관리 담당자는 이들이 서로 관련되어 있으며 항상 동기화 상태를 유지해야 한다는 것을 알 수 있습니다.

// keep in sync with GroupTypes
public enum GroupTypeCodes
{
    OEM,
    CMB
}

// keep in sync with GroupTypesCodes
public enum GroupTypes
{
    TheGroup = GroupTypeCodes.OEM,
    TheOtherGroup = GroupTypeCodes.CMB
}

사용하려면 먼저 코드로 변환합니다.

GroupTypes myGroupType = GroupTypes.TheGroup;
string valueToSaveIntoDatabase = ((GroupTypeCodes)myGroupType).ToString();

그런 다음 보다 편리하게 사용하려면 다음 유형의 열거형에만 사용할 수 있는 확장 기능을 추가할 수 있습니다.

public static string ToString(this GroupTypes source)
{
    return ((GroupTypeCodes)source).ToString();
}

그러면 다음을 수행할 수 있습니다.

GroupTypes myGroupType = GroupTypes.TheGroup;
string valueToSaveIntoDatabase = myGroupType.ToString();

언급URL : https://stackoverflow.com/questions/630803/associating-enums-with-strings-in-c-sharp

반응형