Hello everybody,
today I want to share with the world code, which generates typescript from enum declaration. I suppose everything should be understandable from code itself:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace System
{
public static class AttributesSimplification
{
/*
[Description("Enumerations")]
public enum EnumSample
{
[Description("Choice One")]
ChoiceOne,
[Description("Choice Two")]
ChoiceTwo,
}
gives following ts:
module Enumerations {
export module EnumSample {
export enum Enum {
ChoiceOne = 0,
ChoiceTwo = 2
}
export function describe (enumValue: Enum) {
switch (enumValue) {
case Enum.ChoiceOne:
return "Choice One";
case Enum.ChoiceTwo:
return "Choice Two";
default:
throw Error("Unknown Enum Value");
}
}
}
}
export = Enumerations;
*/
// Since Enum Type implements IConvertible interface we can pass into method enum
//http://stackoverflow.com/questions/79126/create-generic-method-constraining-t-to-an-enum
public static string GetTypeScriptRepresentation<T>() where T :struct , IConvertible
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("T must be an enumerated type");
}
StringBuilder sb = new StringBuilder();
var defaultInstance = new T();
var values = Enum.GetValues(typeof(T)).Cast<T>().ToList();
var descAttribute = (DescriptionAttribute) Attribute.GetCustomAttribute(defaultInstance.GetType(), typeof(DescriptionAttribute));
string moduleName = string.Empty;
if (descAttribute == null || string.IsNullOrEmpty(descAttribute.Description))
{
moduleName = defaultInstance.GetType().Namespace;
}
else
{
moduleName = descAttribute.Description;
}
var enumName = defaultInstance.GetType().Name;
string openingBr = "{";
string closingBr = "}";
sb.Append($"module {moduleName} \r\n {openingBr} \r\n");
sb.Append($"\texport module {enumName} \r\n\t {openingBr} \r\n");
sb.Append($"\t\texport enum Enum \r\n\t\t{openingBr}");
var lastValue = values[values.Count - 1];
foreach (var value in values)
{
var intPresentation = Convert.ToInt32(value as System.Enum);
sb.Append($"\r\n\t\t\t\t{value.ToString()} = {intPresentation.ToString()}" );
if (value.ToString() != lastValue.ToString())
{
sb.Append(",");
}
else
{
sb.Append("\r\n");
}
}
sb.Append($"\t\t{closingBr}");
sb.Append("\r\n\texport function describe (enumValue: Enum) \r\n\t{");
sb.Append("\r\n\t\tswitch (enumValue) \r\n\t\t{\r\n");
foreach (var value in values)
{
sb.Append("\t\t\t\tcase Enum.");
sb.Append(value.ToString());
sb.Append(":");
sb.Append("\r\n\t\t\t\t\t return \"" + GetDescription(value as System.Enum) + "\"");
sb.Append(";\r\n");
}
sb.Append("\t\t\tdefault:\r\n");
sb.Append("\t\t\t\tthrow Error(\"Unknown Enum Value\");");
sb.Append("\r\n\t\t\t}\r\n\t\t }\r\n\t}\r\n}\r\n");
return sb.ToString();
}
public static void WriteFile(string filePath, string content)
{
if (System.IO.File.Exists(filePath))
{
IO.File.Delete(filePath);
}
System.IO.File.WriteAllText(filePath, content);
}
public static string GetDescription(this Enum value)
{
DescriptionAttribute attribute = value.GetType()
.GetField(value.ToString())
.GetCustomAttributes(typeof(DescriptionAttribute), false)
.SingleOrDefault() as DescriptionAttribute;
return attribute == null ? value.ToString() : attribute.Description;
}
public static T GetEnumValueFromDescription<T>(string description)
{
var type = typeof(T);
if (!type.IsEnum)
throw new ArgumentException();
var fields = type.GetFields();
var field = fields
.SelectMany(f => f.GetCustomAttributes(
typeof(DescriptionAttribute), false), (
f, a) => new { Field = f, Att = a }).SingleOrDefault(a => ((DescriptionAttribute)a.Att)
.Description == description);
return field == null ? default(T) : (T)field.Field.GetRawConstantValue();
}
}
}
Some examples of it's job:
AttributesSimplification.GetTypeScriptRepresentation<System.UriHostNameType>()
As result gives the following:
declare module System {
interface Uri {
AbsolutePath: string;
AbsoluteUri: string;
Authority: string;
DnsSafeHost: string;
Fragment: string;
Host: string;
HostNameType: System.UriHostNameType.Enum;
IdnHost: string;
IsAbsoluteUri: boolean;
IsDefaultPort: boolean;
IsFile: boolean;
IsLoopback: boolean;
IsUnc: boolean;
LocalPath: string;
OriginalString: string;
PathAndQuery: string;
Port: number;
Query: string;
Scheme: string;
Segments: string[];
UserEscaped: boolean;
UserInfo: string;
}
}
If you'll have the following declaration:
[Description("DomainModels.Location")]
public enum LocationLevel
{
//Country - ProvincePart levels do not use as they are in nuts codes but can be added if necesary
Country = 1,
CountryPart = 2,
Province = 3,
ProvincePart = 4,
Municipality = 5,
City = 6,
}
Then with following code
AttributesSimplification.GetTypeScriptRepresentation<QCore.Portal.Models.DomainModels.Location.LocationLevel>()
you'll see the following TypeScript generated:
module DomainModels.Location
{
export module LocationLevel
{
export enum Enum
{
Country = 1,
CountryPart = 2,
Province = 3,
ProvincePart = 4,
Municipality = 5,
City = 6
}
export function describe (enumValue: Enum)
{
switch (enumValue)
{
case Enum.Country:
return "Country";
case Enum.CountryPart:
return "CountryPart";
case Enum.Province:
return "Province";
case Enum.ProvincePart:
return "ProvincePart";
case Enum.Municipality:
return "Municipality";
case Enum.City:
return "City";
default:
throw Error("Unknown Enum Value");
}
}
}
}
Take note, how attribute Description was applied.
One more example:
[Description("Models.DomainModels")]
public enum AwardStatus
{
[Description("Still in progress")]
StillInProgress,
[Description("Awarded")]
Awarded,
[Description("Withdrawn")]
Withdrawn
}
AttributesSimplification.GetTypeScriptRepresentation<DomainModels.AwardStatus>()
gives following TS:
module Models.DomainModels
{
export module AwardStatus
{
export enum Enum
{
StillInProgress = 0,
Awarded = 1,
Withdrawn = 2
}
export function describe (enumValue: Enum)
{
switch (enumValue)
{
case Enum.StillInProgress:
return "Still in progress";
case Enum.Awarded:
return "Awarded";
case Enum.Withdrawn:
return "Withdrawn";
default:
throw Error("Unknown Enum Value");
}
}
}
}
So, if you need some kind of enums generation, you can use my utility.