How to serialize enums to XML text - c#

I have currently next field in my serilizable class:
[DataMember]
[XmlElement(DataType = "string")]
public string Type {get;set;}
And in XML it is serilized like:
<Type>Type1</Type>
<Type>Type2</Type>
and so on...
I want it to be enum
public enum MyType
{
Type1,
Type2,
...
}
But how can I serialize it same way as simple string? Is it even possible?

You can do it like this
public enum EmployeeStatus
{
[XmlEnum(Name = "Single")]
One,
[XmlEnum(Name = "Double")]
Two,
[XmlEnum(Name = "Triple")]
Three
}
more about visit msdn.

You can decorate your enum element with XmlEnum:
public enum MyType
{
[XmlEnum(Name="Type1")]
Type1,
[XmlEnum(Name="Type2")]
Type2,
...
}
Give proper Name to make it appear in the XML the way you want.

Related

Best way generate XML with an enum's values and descriptions in C#

I have to send string with xml containing enums serialized to xml.
Those enums are in nuget package, so I can't edit them.
All enums have name, value and description attribute.
public enum FileExtenstion
[Description("XML extension")]
xml = 1,
[Description("TXT extension")]
txt = 2
end enum
My function to get xml from this enum looks like this:
public static string GetFileExtension()
{
var _cache = System.Enum.GetValues(typeof(FileExtension))
.Cast<FileExtension>()
.Select(enumValue => new EnumToXmlSerializer
{
Name = enumValue.ToString(),
Value = (int)enumValue,
Description = enumValue.GetDescription()
}).ToList();
(...)
}
public class EnumToXmlSerializer
{
public string Name { get; set; }
public int Value { get; set; }
public string Description { get; set; }
}
Works well.
But I have a lot of enums to convert and better way will be to prepare some parametrized function with convert string with name of enum ("FileExtension") to type.
I haven't idea how to convert enum name (not enum every value name but enum type name) and convert its to type. In stackoverflow I found only conversion for enum values not all types.
I'm looking for solution to prepare function like this:
public string GetXmlFromEnumTypeName("FileExtension")
to get:
<enums>
<enum><name>xml</name><value>1</value><description>XML extension</description></enum>
<enum><name>txt</name><value>2</value><description>TXT extension</description></enum>
</enums>
I suppose there will be one line to change my GetFileExtension function but I usually get it wrong about things like that.

Serialize Flags enum with two equal values

I want to define a flag enum like the following:
[Flags]
[Serializable]
public enum Numbers
{
[XmlEnum(Name = "One")]
One = 0x1,
[XmlEnum(Name = "Two")]
Two = 0x2,
[XmlEnum(Name = "Three")]
Three = 0x4,
[XmlEnum(Name = "OddNumbers")]
OddNumbers = One | Three,
[XmlEnum(Name = "EvenNumbers")]
EvenNumbers = Two,
[XmlEnum(Name = "AllNumbers")]
AllNumbers = One | Two | Three
}
Suppose I create an object which has a Numbers property and I set that property to EvenNumbers. Today, only Two is included in property, but I want to specify EvenNumbers so that if I add Four in the future it will be included in the property as well.
However, if I serialize this object using XmlSerializer.Serialize, the XML will say Two because today this is the same underlying value.
How can I force the serializer to serialize this property as EvenNumbers?
Do something like that: Mark the Number property as XmlIgnore and create another property type of string for return the string value of enum.
[Serializable]
public class NumberManager
{
[XmlIgnore]
public Numbers Numbers { get; set; }
[XmlAttribute(AttributeName="Numbers")]
public string NumbersString
{
get { return Numbers.ToString(); }
set { Numbers = (Numbers) Enum.Parse(typeof (Numbers), value); }
}
}
Then serialize the NumberManager.
I hope it helps.

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.

How to set two values for same definition in enum, C#

I am trying to compare values that I am getting from web service, but sometimes I get int value, sometimes i get string. So it would be great that i could only check for Type.value1.
for example:
enum Type { value1 = 1 , value1="one"}
and like that for more value2, etc...
But of course, I cannot do this because it I cannot add two definitons for value1.
Sometimes a type that behaves mostly like an enum but has some richer behaviour can be very useful:
public sealed class MyFakeEnum {
private MyFakeEnum(int value, string description) {
Value = value;
Description = description;
}
public int Value { get; private set; }
public string Description { get; private set; }
// Probably add equality and GetHashCode implementations too.
public readonly static MyFakeEnum Value1 = new MyFakeEnum(1, "value1");
public readonly static MyFakeEnum Value2 = new MyFakeEnum(2, "value2");
}
You can consider adding attributes to the enums and use reflection.
enum Type
{
[Description("One")]
value1 = 1
}
I also make use of using decorating the enum with a description attribute as described by BSoD_ZA. But I would suggest that you then implement an extension method for the enumeration to obtain the string description for example:
public static class EnumExtension
{
public static string ToDescription<TEnum>(this TEnum enumValue) where TEnum : struct
{
return ReflectionService.GetClassAttribute<DescriptionAttribute>(enumValue);
}
}
enum Type
{
[Description("One")]
value1 = 1
}
var value = Type.Value1;
Console.Writeline(value.ToDescription());

C# "Enum" Serialization - Deserialization to Static Instance

Suppose you have the following class:
class Test : ISerializable {
public static Test Instance1 = new Test {
Value1 = "Hello"
,Value2 = 86
};
public static Test Instance2 = new Test {
Value1 = "World"
,Value2 = 26
};
public String Value1 { get; private set; }
public int Value2 { get; private set; }
public void GetObjectData(SerializationInfo info, StreamingContext context) {
//Serialize an indicator of which instance we are - Currently
//I am using the FieldInfo for the static reference.
}
}
I was wondering if it is possible / elegant to deserialize to the static instances of the class?
Since the deserialization routines (I'm using BinaryFormatter, though I'd imagine others would be similar) look for a constructor with the same argument list as GetObjectData(), it seems like this can't be done directly . . Which I would presume means that the most elegant solution would be to actually use an enum, and then provide some sort of translation mechanism for turning an enum value into an instance reference. However, I personally like that the "Enum"'s choices are directly linked with their data.
How might one go about this?
If you need more data with with the Enums, consider using attributes. Example below.
class Name : Attribute
{
public string Text;
public Name(string text)
{
this.Text = text;
}
}
class Description : Attribute
{
public string Text;
public Description(string text)
{
this.Text = text;
}
}
public enum DaysOfWeek
{
[Name("FirstDayOfWeek")]
[Description("This is the first day of 7 days")]
Sunday = 1,
[Name("SecondDayOfWeek")]
[Description("This is the second day of 7 days")]
Monday= 2,
[Name("FirstDayOfWeek")]
[Description("This is the Third day of 7 days")]
Tuesday= 3,
}
Perhaps this will allow you to provide more information with the Enums. You can access the attributes through reflection. If you need an example to retrieve the attribute I can provide that as well but I'm trying to keep this somewhat short.
Use Enum.Parse...Suppose you have the following:
Enum myEnum{
Foo = 1,
Bar = 2,
Baz = 3
};
Then
myEnum myE = myEnum.Foo; /* Default! */
myE = (myEnum)Enum.Parse(myE.GetType(), "Baz");
/* Now, myE should be Baz! */
Console.WriteLine("Enum Selected: {0}", myE.ToString());
The above sample serves to illustrate how to convert a string literal into an enum. I hope this is what you are looking for.

Categories