get enumMember value property from an enum - c#

I have an enum like this :
[JsonConverter(typeof(StringEnumConverter))]
public enum Process
{
[EnumMember(Value = "N/A")]
None,
[EnumMember(Value = "Something")]
Something
}
When I try to read its value like this:
Process.Status = JsonConvert.SerializeObject(Process.None);
I am getting 0
ALso toString() doesn't work as I get "None" and not "N/A".
How do i solve this?

Related

Is It Possible to Map to an Enum With an Alias?

I have a http request coming that has a property for a value. There are 2 possible options for this value, let's say Standard and Boosted. I'm using an enum for this.
I also need to get the same value from my database, but in database this value is called something else. For example they are called TypeS and TypeB.
I'm looking for an easy way to map them to each other.
I've tried using an Alias but that doesn't seem to be working.
pubic enum RequestType
{
[Alias("TypeS")]
Standard,
[Alias("TypeB")]
Boosted
}
public class ReturnObject
{
public RequestType type {get; set;}
}
I'm getting the record from the database using a stored proc.
db.SqlList<ReturnObject>("EXEC SomeStoredProc #someParameter",
new { someParameter }).ToList();
ReturnObject.type is always Standard even tho the Database returns TypeB which tells me it instantiates the enum with the default value.
In the latest v5.5.1 on MyGet, OrmLite supports char enums, e.g
[EnumAsChar]
public enum SomeEnum
{
Value1 = 'A',
Value2 = 'B',
Value3 = 'C',
Value4 = 'D'
}
Otherwise the only other ways OrmLite supports persisting enums is by Name (default):
public enum SomeEnum
{
Value1,
Value2,
Value3,
Value4,
}
By Enum integer value:
[Flags] //or [EnumAsInt]
public enum SomeEnum
{
None = 0,
Value1 = 1 << 0,
Value2 = 1 << 1,
Value3 = 1 << 2,
Value4 = 1 << 3,
}
Or by char value as shown in my first example.
Alternatively you'd need to use the name it's stored in the database as, but you can have it serialized using a different value by annotating it with [EnumMember], e.g:
[DataContract]
public enum SomeEnum
{
[EnumMember(Value = "VALUE 1")]
Value1,
[EnumMember(Value = "VALUE 2")]
Value2,
[EnumMember(Value = "VALUE 3")]
Value3,
[EnumMember(Value = "VALUE 4")]
Value4,
}

ServiceStack.Text.EnumMemberSerializer not working with Swagger plugin

I'm using ServiceStack v 3.9.71 and the ServiceStack.Text.EnumMemberSerializer assembly to serialize enums into readable text.
This works great, my enum values are serialized into the name I've specified using the EnumMemberAttribute.
The problem, though, is Swagger does not use my names. My guess is it just calls the .ToString() method on the enum values rather than the EnumMemberAttribute value.
Here is the order in which I setup the serialization. (In AppHost):
new EnumSerializerConfigurator()
.WithEnumTypes(new Type[] { typeof(MyEnum) })
.Configure();
Plugins.Add(new SwaggerFeature());
It doesn't seem to matter if the enum serializer is set before or after the swagger feature is added.
You are correct that the Swagger code does not use ServiceStack.Text.EnumMemberSerializer when parsing enum values. It only uses an Enum.GetValues here. Note that this is still the same in v4.
You can submit a pull request to make this change, but I'm not familiar with EnumMemberSerialzer and how it allows for retrieving the list of enum options. You may instead be able to use a string property decorated with ApiAllowableValues to achieve the affect.
Here is the solution I came up with (with the help of bpruitt-goddard, thanks mate):
The enum:
public enum MyEnum
{
[EnumMember(Value = "Value One")]
Value1 = 1,
[EnumMember(Value = "Value Two")]
Value2 = 2,
[EnumMember(Value = "Value Three")]
Value3 = 3
}
The client object:
public class MyClientObject
{
[Description("The name")]
public string Name {get;set;}
[Description("The client object type")]
[ApiAllowableValues("MyEnum", "Value One", "Value Two", "Value Three")]
public MyEnum MyEnum { get; set; }
}
Inside the AppHost:
new EnumSerializerConfigurator()
.WithEnumTypes(new Type[] { typeof(MyEnum) })
.Configure();
Now the enum is serialized properly and the Swagger documentation is correct. The only issue with this is having the names in two different places. Perhaps there is a way to check the names match via a unit test.
I came up with, in my opinion, a better solution. I wrote a class that extends the ApiAllowableValuesAttribute:
public class ApiAllowableValues2Attribute : ApiAllowableValuesAttribute
{
public ApiAllowableValues2Attribute(string name, Type enumType)
: base(name)
{
List<string> values = new List<string>();
var enumTypeValues = Enum.GetValues(enumType);
// loop through each enum value
foreach (var etValue in enumTypeValues)
{
// get the member in order to get the enumMemberAttribute
var member = enumType.GetMember(
Enum.GetName(enumType, etValue)).First();
// get the enumMember attribute
var enumMemberAttr = member.GetCustomAttributes(
typeof(System.Runtime.Serialization.EnumMemberAttribute), true).First();
// get the enumMember attribute value
var enumMemberValue = ((System.Runtime.Serialization.EnumMemberAttribute)enumMemberAttr).Value;
values.Add(enumMemberValue);
}
Values = values.ToArray();
}
}
The client object:
public class MyClientObject
{
[Description("The name")]
public string Name {get;set;}
[Description("The client object type")]
[ApiAllowableValues2("MyEnum", typeof(MyEnum))]
public MyEnum MyEnum { get; set; }
}
Now you don't have to specify the names again or worry about a name change breaking your Swagger documentation.

Enum.ToString() that abides EnumMemberAnnotation

I have an enum annotated with EnumMember to facilitate JSON.NET serialization similar to the following:
[DataContract]
[JsonConverter(typeof(StringEnumConverter))]
public enum Status
{
[EnumMember(Value = "NOT_ADMITTED")]
NotAdmitted,
[EnumMember(Value = "ADMITTED")]
Admitted
}
Now, independent of the JSON.NET serialization I'd like to I'd like to convert instances of the enum to a string while abiding by the EnumMember annotations in the data contract, e.g.:
aStatusInstance.ToString() == "NOT_ADMITTED".
Any suggestions? Thanks!
Update: My Solution
I modified the code in the accepted answer to create an extension method to retrieve the EnumMember Value:
public static string GetEnumMemberValue(this Enum enumValue)
{
var type = enumValue.GetType();
var info = type.GetField(enumValue.ToString());
var da = (EnumMemberAttribute[])(info.GetCustomAttributes(typeof(EnumMemberAttribute), false));
if (da.Length > 0)
return da[0].Value;
else
return string.Empty;
}
I would use the Description Attribute and decorate the enum with the same value as the EnumMember:
[DataContract]
[JsonConverter(typeof(StringEnumConverter))]
public enum Status
{
[EnumMember(Value = "NOT_ADMITTED")]
[Description("NOT_ADMITTED")]
NotAdmitted,
[EnumMember(Value = "ADMITTED")]
[Description("ADMITTED")]
Admitted
}
You can use this code snippet to parse it. This is written as an extension of the Enum class:
public static string GetDescription(this Enum enumValue)
{
Type type = enumValue.GetType();
FieldInfo info = type.GetField(enumValue.ToString());
DescriptionAttribute[] da = (DescriptionAttribute[])(info.GetCustomAttributes(typeof(DescriptionAttribute), false));
if (da.Length > 0)
return da[0].Description;
else
return string.Empty;
}
You can then compare it with the following:
aStatusInstance.GetDescription() == "NOT_ADMITTED"

set Enums using reflection

How to set Enums using reflection,
my class have enum :
public enum LevelEnum
{
NONE,
CRF,
SRS,
HLD,
CDD,
CRS
};
and in runtime I want to set that enum to CDD for ex.
How can I do it ?
Try use of class Enum
LevelEnum s = (LevelEnum)Enum.Parse(typeof(LevelEnum), "CDD");
public class MyObject
{
public LevelEnum MyValue {get;set,};
}
var obj = new MyObject();
obj.GetType().GetProperty("MyValue").SetValue(LevelEnum.CDD, null);
value = (LevelEnum)Enum.Parse(typeof(LevelEnum),"CDD");
So basically you just parse the string corresponding to the enum value that you wish to assign to the variable. This will blow if the string is not a defined member of the enum. you can check that with Enum.IsDefined(typeof(LevelEnum),input);

How to read enum value in ASP.Net?

My enum structure is this
public enum UserRole
{
Administrator = "Administrator",
Simple_User = "Simple User",
Paid_User = "Paid User"
}
Now i want to read this enum value by using its name suppose
String str = UserRole.Simple_User;
it gives me "Simple User" in str instead of "Simple_User"
How we can do this???
You can do a friendly description like so:
public enum UserRole
{
[Description("Total administrator!!1!one")]
Administrator = 1,
[Description("This is a simple user")]
Simple_User = 2,
[Description("This is a paid user")]
Paid_User = 3,
}
And make a helper function:
public static string GetDescription(Enum en)
{
Type type = en.GetType();
MemberInfo[] info = type.GetMember(en.ToString());
if (info != null && info.Length > 0)
{
object[] attrs = info[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attrs != null && attrs.Length > 0)
{
return ((DescriptionAttribute)attrs[0]).Description;
}
}
return en.ToString();
}
And use it like:
string description = GetDescription(UserRole.Administrator);
Okay so by now you know that enum really is a list of numbers that you can give a handy string handle to like:
public enum ErrorCode
{
CTCLSM = 1,
CTSTRPH = 2,
FBR = 3,
SNF = 4
}
Also, as #StriplingWarrior showed, you can go so far by getting the enum string name and replacing underscores etc. But what I think you want is a way of associating a nice human string with each value. How about this?
public enum ErrorCode
{
[EnumDisplayName("Cataclysm")]
CTCLSM = 1,
[EnumDisplayName("Catastrophe")]
CTSTRPH = 2,
[EnumDisplayName("Fubar")]
FBR = 3,
[EnumDisplayName("Snafu")]
SNF = 4
}
Okay there's probably something in System.ComponentModel that does this - let me know. The code for my solution is here:
[AttributeUsage(AttributeTargets.Field)]
public class EnumDisplayNameAttribute : System.Attribute
{
public string DisplayName { get; set; }
public EnumDisplayNameAttribute(string displayName)
{
DisplayName = displayName;
}
}
And the funky Enum extension that makes it possible:
public static string PrettyFormat(this Enum enumValue)
{
string text = enumValue.ToString();
EnumDisplayNameAttribute displayName = (EnumDisplayNameAttribute)enumValue.GetType().GetField(text).GetCustomAttributes(typeof(EnumDisplayNameAttribute), false).SingleOrDefault();
if (displayName != null)
text = displayName.DisplayName;
else
text = text.PrettySpace().Capitalize(true);
return text;
}
So to get the human-friendly value out you could just do ErrorCode.CTSTRPH.PrettyFormat()
Hmm, enums can't have string values. From MSDN's Enum page:
An enumeration is a set of named constants whose underlying type is any integral type except Char.
To get the string version of the enum use the Enum's ToString method.
String str = UserRole.Simple_User.ToString("F");
I'm a little confused by your question, because C# doesn't allow you to declare enums backed by strings. Do you mean that you want to get "Simple User", but you're getting "Simple_User" instead?
How about:
var str = UserRole.Simple_User.ToString().Replace("_", " ");
You can do this by attribute, but really I think using an enum like this is possibly the wrong way to go about things.
I would create a user role interface that exposes a display name property, then implement that interface with a new class for each role, this also let's you add more behaviour in the future.
Or you could use an abstract class so any generic behaviour doesn't get duplicated...

Categories