열거 형의 유형이 int 여야하기 때문에 다음이 불가능하다는 것을 알고 있습니다.
enum GroupTypes
{
TheGroup = "OEM",
TheOtherGroup = "CMB"
}
내 데이터베이스에서 나는 (incomprehensive 코드로 필드를 얻을 OEM및CMB s) . 이 분야를 enum이해하기 쉬운 것으로 만들고 싶습니다 . 대상이 가독성이면 솔루션이 간결해야합니다.
다른 옵션이 있습니까?
열거 형의 유형이 int 여야하기 때문에 다음이 불가능하다는 것을 알고 있습니다.
enum GroupTypes
{
TheGroup = "OEM",
TheOtherGroup = "CMB"
}
내 데이터베이스에서 나는 (incomprehensive 코드로 필드를 얻을 OEM및CMB s) . 이 분야를 enum이해하기 쉬운 것으로 만들고 싶습니다 . 대상이 가독성이면 솔루션이 간결해야합니다.
다른 옵션이 있습니까?
답변:
더 열거 형처럼 보이기 때문에 메서드 대신 클래스에서 속성 을 사용 하고 싶습니다.
로거의 예는 다음과 같습니다.
public class LogCategory
{
private LogCategory(string value) { Value = value; }
public string Value { get; 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 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);
ToString반환 하는 메소드를 재정의했습니다 Value. 그런 다음 문자열에 암시 적 캐스트 연산자를 제공했습니다. public static implicit operator String(LogCategory category) { return Value; }.
확장 모델을 사용할 수도 있습니다.
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());
public static string ToDescriptionString(this Enum ...명시 적으로 입력하지 않고을 사용하십시오 MyEnum.
상수가있는 정적 클래스를 사용하는 것은 어떻습니까?
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?
}
}
GroupTypes정적 클래스이기 때문에 인수 유형으로 전달할 수 없습니다 . 그것이 미엔조차도 해결하는 문제입니다. 이 경우 대신이해야 할 것 void DoSomething(string groupType)그 다음 어떤 수단을 groupType가질 수있다 어떠한 문자열 값을 당신이 그 유효하지 않은 유형에 대비해야하고이를 처리하는 방법을 결정하는 수단도 값은 당신이 기대되지 않는다는을, (예를 들어, 예외를 던져서). Mien의 답변조차도 유효한 입력 수를 LogCategory클래스가 정의한 옵션으로 제한하여 문제를 해결합니다 .
열거의 항목에 특성을 추가 한 다음 리플렉션을 사용하여 특성에서 값을 가져올 수 있습니다.
속성을 적용하려면 "field"지정자를 사용해야합니다.
enum GroupTypes
{
[field:Description("OEM")]
TheGroup,
[field:Description("CMB")]
TheOtherGroup
}
그런 다음 열거 형 유형의 정적 필드 (이 경우 GroupTypes) DescriptionAttribute를 반영하고 리플렉션을 사용하여 찾고 있던 값을 가져옵니다 .
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속성이 적용되는지 여부를 결정할 수있는 경우 위의 내용 을 반환하기로 선택했습니다 .
실제로 매우 쉽게 할 수 있습니다. 다음 코드를 사용하십시오.
enum GroupTypes
{
OEM,
CMB
};
그런 다음 각 열거 형 요소의 문자열 값을 얻으려면 다음 코드 줄을 사용하십시오.
String oemString = Enum.GetName(typeof(GroupTypes), GroupTypes.OEM);
나는 과거 에이 방법을 성공적으로 사용했으며 상수 클래스를 사용하여 문자열 상수를 유지했지만 둘 다 잘 작동하지만 선호하는 경향이 있습니다.
정적 클래스에 상수를 추가하십시오. Type으로 끝나지 않지만 읽을 수 있고 체계적인 상수가 있습니다.
public static class GroupTypes {
public const string TheGroup = "OEM";
public const string TheOtherGroup = "CMB";
}
다음을 포함하는 DB에 대한 두 번째 열거 형을 작성하십시오.
enum DBGroupTypes
{
OEM = 0,
CMB = 1
}
이제 Enum.Parse를 사용하여 문자열 "OEM"및 "CMB"에서 올바른 DBGroupTypes 값을 검색 할 수 있습니다. 그런 다음 해당 값을 int로 변환하고 모델에서 추가로 사용하려는 올바른 열거에서 올바른 값을 검색 할 수 있습니다.
수업을 사용하십시오.
편집 : 더 나은 예
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.");
}
}
이 문제를 처리하는 또 다른 방법은 열거 형 값과 문자열 목록을 매핑하는 문자열 배열을 열거하는 것입니다.
public enum GroupTypes
{
TheGroup = 0,
TheOtherGroup
}
string[] GroupTypesStr = {
"OEM",
"CMB"
};
다음과 같이 사용할 수 있습니다.
Log.Write(GroupTypesStr[(int)GroupTypes.TheOtherGroup]);
CMB를 프롬프트합니다
장점 :
단점 :
다음은 열거 형 값을 문자열로 얻는 데 사용한 확장 방법입니다. 먼저 여기 열거 형이 있습니다.
public enum DatabaseEnvironment
{
[Description("AzamSharpBlogDevDatabase")]
Development = 1,
[Description("AzamSharpBlogQADatabase")]
QualityAssurance = 2,
[Description("AzamSharpBlogTestDatabase")]
Test = 3
}
Description 속성은 System.ComponentModel에서 가져 왔습니다.
그리고 여기 내 확장 방법이 있습니다 :
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());
}
}
사전을 사용하여 찾아보기 테이블을 고려 했습니까?
enum GroupTypes
{
TheGroup,
TheOtherGroup
}
Dictionary<string, GroupTypes> GroupTypeLookup = new Dictionary<string, GroupTypes>();
// initialize lookup table:
GroupTypeLookup.Add("OEM", TheGroup);
GroupTypeLookup.Add("CMB", TheOtherGroup);
그런 다음 GroupTypeLookup.TryGetValue ()를 사용하여 읽을 때 문자열을 찾을 수 있습니다.
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 #은 열거 된 문자열을 지원하지 않지만 대부분의 경우 목록 또는 사전을 사용하여 원하는 효과를 얻을 수 있습니다.
예 : 합격 / 불합격 결과를 인쇄하려면
List<string> PassFail = new List<string> { "FAIL", "PASS" };
bool result = true;
Console.WriteLine("Test1: " + PassFail[result.GetHashCode()]);
나는 그것을 열거 형을 피하기 위해 클래스로 만들 것입니다. 그런 다음 typehandler를 사용하면 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"); }
}
사전을 만들고 코드를 키로 사용합니다.
편집 : 리버스 조회 (키 찾기)에 대한 의견을 다루는 것은별로 효과적이지 않습니다. 이것이 필요한 경우 처리 할 새 클래스를 작성합니다.
첫 번째 질문-데이터베이스 자체에 액세스 할 수 있습니까? 이것은 데이터베이스에서 정규화되어야하며, 그렇지 않으면 모든 솔루션에서 오류가 발생하기 쉽습니다. 내 경험상, "OEM"과 "CMB"로 가득 찬 데이터 필드는 "oem"과 같은 것들과 다른 '스크랩 데이터'가 시간이 지남에 따라 섞이는 경향이 있습니다 .... 정규화 할 수 있다면 키를 사용할 수 있습니다 Enum과 같은 요소를 포함하는 테이블에 더 깔끔한 구조로 완료되었습니다.
그것이 가능하지 않다면, 나는 당신의 Enum을 만들고 당신의 문자열을 Enum으로 구문 분석하는 클래스를 만듭니다. 이것은 최소한 비표준 항목을 처리하는 데 약간의 유연성을 제공하고 Enum.Parse / Reflection / etc 등을 사용하는 해결 방법을 수행하는 것보다 오류를 잡거나 처리하는 데 훨씬 더 많은 유연성을 제공합니다. 사전은 작동하지만 사례 문제 등이 있으면 고장날 수 있습니다.
할 수 있도록 수업을 쓰는 것이 좋습니다.
// I renamed this to GroupType, since it sounds like each element has a single type...
GroupType theType = GroupTypeParser.GetGroupType(theDBString);
이를 통해 DB를 변경하지 않고도 대부분의 가독성을 유지할 수 있습니다.
올바르게 이해하면 문자열에서 열거 형으로 변환해야합니다.
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");
원하는 경우 열거 형의 제네릭으로 더 멋지게 만들 수 있습니다.
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;
}
}
}
또는 Linq 사용
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의 대답에 따라 조금 더 나아가서 Generic으로 만들려고했지만 거의 거기에있는 것처럼 보이지만 하나의 사례는 여전히 저항하고 아마도 코드를 조금 단순화 할 수 있습니다.
누군가 내가 내가 개선 할 수있는 방법을보고 특히 문자열에서 할당 할 수 없으므로 작동하게하는 경우 여기에 게시하십시오.
지금까지 나는 다음과 같은 결과를 얻었습니다.
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"); } }
}
.Net Core 3.0 / C # 8.0의 새로운 기능 (작업 환경에서 프로젝트를 업그레이드 할 수있는 경우)은 간단한 전환 설명입니다. 하루가 끝나면 몇 년 동안 사용했던 것과 같은 오래된 지루한 스위치 설명입니다.
여기서 유일한 차이점은 switch 문이 새로운 소송을 받았다는 것입니다.
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)),
};
당신은 내가 복사하는 위의 코드 것을 알 수 있습니다 여기가 실제로 PARAM으로 열거를 사용하고 있습니다.
그것은 정확히 당신이 원하는 것이 아니며 (그리고 OP, 오랫동안 OP가 요청하는 것과 비슷한 것을 원했습니다) 실제로는 이것이 MS의 올리브 가지라고 생각합니다. JMO.
그것이 누군가를 돕기를 바랍니다!
이전 답변에서 언급 한 구조를 사용했지만 복잡성을 제거했습니다. 나에게 이것은 문자열 열거를 만드는 것과 가장 비슷했습니다. 열거 형과 같은 방식으로 사용됩니다.
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;
}
@Even (via class X및 public static X회원)이 제안한대로 몇 가지 열거 형을 구현했습니다. 요즘 .Net 4.5부터는 옳습니다. ToString() 방법 있습니다.
이제 모든 것을 열거 형으로 다시 구현하고 있습니다.
이것은 강력한 형식의 매개 변수 또는 문자열 로 사용하는 방법입니다 .
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");
}
두 개의 열거 형을 사용할 수 있습니다. 하나는 데이터베이스를위한 것이고 다른 하나는 가독성을위한 것입니다.
적은 비용으로 동기화 상태를 유지해야합니다. 값을 설정할 필요는 없으며 위치를 동일하게 설정하면되지만 값을 설정하면 두 열거 형이 관련되어 있고 오류가 열거 형 멤버를 다시 정렬하는 것을 막을 수 있습니다. 그리고 의견은 유지 보수 승무원이 이것들이 관련되어 있고 동기화 상태를 유지해야한다는 것을 알려줍니다.
// 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();
enum따라 의도 된 가치 변화는 무의식적으로 다른 것을 망칠 수있다.
나는 기본적으로 @ArthurC의 Reflection 답변을 찾고있었습니다.
그의 답변을 약간 확장하기 위해 일반적인 기능을 사용하여 더 잘 만들 수 있습니다.
// If you want for a specific Enum
private static string EnumStringValue(GroupTypes e)
{
return EnumStringValue<GroupTypes>(e);
}
// Generic
private static string EnumStringValue<T>(T enumInstance)
{
return Enum.GetName(typeof(T), enumInstance);
}
그럼 당신은 당신이 가진 모든 것을 포장 할 수 있습니다
EnumStringValue(GroupTypes.TheGroup) // if you incorporate the top part
또는
EnumStringValue<GroupTypes>(GroupTypes.TheGroup) // if you just use the generic
@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("Logout");
public static AgentAction Logout = new AgentAction("Logout");
public static implicit operator string(AgentAction action) { return action.ToString(); }
}
이 클래스 추가
public class DatabasePreference {
public DatabasePreference([CallerMemberName] string preferenceName = "") {
PreferenceName = preferenceName;
}
public string PreferenceName;
}
이 작업은 CallerMemberName코딩을 최소화하기 위해 사용 하고 있습니다
사용 :
//Declare names
public static DatabasePreference ScannerDefaultFlashLight = new DatabasePreference();
public static DatabasePreference ScannerQrCodes = new DatabasePreference();
public static DatabasePreference Scanner1dCodes = new DatabasePreference();
그것을 테스트하십시오 :
Console.WriteLine(ScannerDefaultFlashLight.PreferenceName);
Console.WriteLine(ScannerDefaultFlashLight.Scanner1dCodes);
산출:
ScannerDefaultFlashLight
Scanner1dCodes
다른 의견에 따르면, 이것이 내가 생각해 낸 것입니다. 이 방법은 상수 값을 얻으려는 경우 .Value를 입력하지 않아도됩니다.
다음과 같은 모든 문자열 열거 형에 대한 기본 클래스가 있습니다.
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
}
JsonConverter는 다음과 같습니다.
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으로 직렬화 할 수도 있습니다.
속성에 문자열을 저장하는 것과 같은 강력한 것이 필요하지 않았습니다. 난 그냥 MyEnum.BillEveryWeek"매주 청구서"또는 MyEnum.UseLegacySystem"레거시 시스템 사용"으로 바꾸어야했습니다. 기본적으로 낙타를 사용하여 열거 형을 개별 소문자로 나눕니다.
public static string UnCamelCase(this Enum input, string delimiter = " ", bool preserveCasing = false)
{
var characters = input.ToString().Select((x, i) =>
{
if (i > 0 && char.IsUpper(x))
{
return delimiter + x.ToString(CultureInfo.InvariantCulture);
}
return x.ToString(CultureInfo.InvariantCulture);
});
var result = preserveCasing
? string.Concat(characters)
: string.Concat(characters).ToLower();
var lastComma = result.LastIndexOf(", ", StringComparison.Ordinal);
if (lastComma > -1)
{
result = result.Remove(lastComma, 2).Insert(lastComma, " and ");
}
return result;
}
MyEnum.UseLegacySystem.UnCamelCase() "레거시 시스템 사용"출력
여러 플래그가 설정되어 있으면 일반 영어 (마지막 쉼표 대신 "and"를 제외하고 쉼표로 구분)로 바뀝니다.
var myCustomerBehaviour = MyEnum.BillEveryWeek | MyEnum.UseLegacySystem | MyEnum.ChargeTaxes;
Console.WriteLine(myCustomerBehaviour.UnCamelCase());
//outputs "bill every week, use legacy system and charge taxes"