While you work on middleware integration applications, it quite common that the application being interacted are having different message exchange formats. Popular message exchange formats are XML & JSON.
Assume you are integrating an application which exposes data in XML format and you need send that data to another application which expects data to be sent in JSON.
So with XML de serilization you build an object and the object needs to de serialized into JSON text.
Problem statement
If your XSD has enumeration values with spaces, then upon generating the proxies, your .NET enum values will have XmlEnumAttribute applied to them.
Problem statemen example:
Let’s consider below XSD for LoanType enumeration.
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="Home Loan"/>
<xs:enumeration value="Student Loan"/>
<xs:enumeration value="Personal Loan"/>
<xs:enumeration value="Gold Loan"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
Then upon generating the proxy classes the LoanType enum will look like below in C# .NET.
public enum LoanType
{
[XmlEnumAttribute("Home Loan")]
HomeLoan,
[XmlEnumAttribute("Student Loan")]
StudentLoan,
[XmlEnumAttribute("Personal Loan")]
PersonalLoan,
[XmlEnumAttribute("Gold Loan")]
GoldLoan
}
If you use popular JOSN Serializer Newtonsoft.Json, then you will not get the exact values as defined XmlEnumAttribute in a more readable fashion.
The JSON de serialization text for LoanType will have either integer value(0, 1, 2, 3). This might not be acceptable for the receiving system. Then you need write custom logic in getting the XmlEnumAttribute values for enum values.
Solution to the problem
We can use Reflection to solve the problem here to get the XmlEnumAttribute for enum values. Something like below in C# .NET.
{
public static Dictionary<string, string> GetXmlEnumAttributeValues(IEnumerable<Type> forTypes)
{
IEnumerable<Type> enumTypes = GetEnumsFieldTypes(forTypes);
Dictionary<string, string> enumXmlEnumAttributeValues = new Dictionary<string, string>();
foreach (Type enumType in enumTypes)
{
MemberInfo[] memberInfos =
enumType.GetMembers
(BindingFlags.Public | BindingFlags.Static);
foreach (MemberInfo memberInfo in memberInfos)
{
XmlEnumAttribute xmlEnumAttribute =
memberInfo.GetCustomAttributes
(typeof(XmlEnumAttribute), false).FirstOrDefault()
as XmlEnumAttribute;
if (xmlEnumAttribute != null)
{
string keyName = enumType.FullName + memberInfo.Name;
if (!enumXmlEnumAttributeValues.ContainsKey(keyName))
{
enumXmlEnumAttributeValues.Add(keyName, xmlEnumAttribute.Name);
}
}
}
}
return enumXmlEnumAttributeValues;
}
private static IEnumerable<Type> GetEnumsFieldTypes
(IEnumerable<Type> types)
{
List<Type> allEnumtypes = new List<Type>();
foreach (Type type in types)
{
PropertyInfo[] propertyInfos = type.GetProperties();
var enumTypes = from p in propertyInfos
where p.PropertyType.IsEnum
select p.PropertyType;
allEnumtypes.AddRange(enumTypes);
}
return allEnumtypes;
}
}
ReflectionHelper.GetXmlEnumAttributeValues(new System.Collections.Generic.List<Type>{ typeof(Loan) });
private static string GetEnumText(Type enumtype, string value)
{
string keyName = enumtype.FullName + value;
if (enumValues.ContainsKey(keyName))
{
value = enumValues[keyName];
}
return value;
}
Then if you want to XmlEnumAttribute for a enum value, you can pass in the class type defining the enum. In this case it could be a "LoanType" type like below:
{
public LoanType LoanType;
}
Then when you have Loan object you can get its LoanType enum’s XmlEnumAttribute value like below:
string enumText = GetEnumText(typeof(LoanType), loan. LoanType);
Then enumText would have “Home Loan” instead of default JSON de searialized values of integer values.
No comments:
Post a Comment