string representation of an enum (estring)? - c#

i need an enum or something similiar to do something like this:
public enum MyStringEnum {
[StringValue("Foo A")] Foo = "A",
[StringValue("Foo B")] Foo = "B" }
is this possible? my example, i return back a dataset with a value represented as either A,B,C,D,E .. i need a solution to return this as a string representation?
i guess the obvious would be to create an extension method or something which just had a switch statement in and return a string .. any other cleaner solutions?
regards,
dave

Here is something we use for our MVC applications to retrieve a display name for our enums. It uses a custom attribute and an extension method to retrieve the enum display name.
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class EnumDisplayNameAttribute : Attribute
{
public EnumDisplayNameAttribute(string displayName)
{
DisplayName = displayName;
}
public string DisplayName { get; set; }
}
public static string GetDisplayName(this Enum enumType)
{
var displayNameAttribute = enumType.GetType()
.GetField(enumType.ToString())
.GetCustomAttributes(typeof(EnumDisplayNameAttribute), false)
.FirstOrDefault() as EnumDisplayNameAttribute;
return displayNameAttribute != null ? displayNameAttribute.DisplayName : Enum.GetName(enumType.GetType(), enumType);
}
Usage on the enum:
public enum Foo
{
[EnumDisplayName("Foo Bar")]
Bar = 0
}
Getting back the display name:
var f = Foo.Bar;
var name = f.GetDisplayName();

Would it be an option not to use enum and use structs instead?
struct FooEnum
{
private int value;
private string name;
private FooEnum(int value, string name)
{
this.name = name;
this.value = value;
}
public static readonly FooEnum A = new FooEnum(0, "Foo A");
public static readonly FooEnum B = new FooEnum(1, "Foo B");
public static readonly FooEnum C = new FooEnum(2, "Foo C");
public static readonly FooEnum D = new FooEnum(3, "Foo D");
public override string ToString()
{
return this.name;
}
//TODO explicit conversion to int etc.
}
You could then use FooEnum like an enum with an own ToString() overload:
FooEnum foo = FooEnum.A;
string s = foo.ToString(); //"Foo A"

If you want to do something like this:
MyStringEnum value = MyStringEnum.A;
string description = value.GetDescription();
// description == "Foo A"
Setup your enum like this:
public enum MyStringEnum
{
[Description("Foo A")]
A,
[Description("Foo B")]
B
}
And use a utility/extension method that reads the attribute:
public static string GetDescription(this MyStringEnum enumerationValue)
{
Type type = enumerationValue.GetType();
string name = enumerationValue.ToString();
//Tries to find a DescriptionAttribute for a potential friendly name for the enum
MemberInfo[] member = type.GetMember(name);
if (member != null && member.Length > 0)
{
object[] attributes = member[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes != null && attributes.Length > 0)
{
//Pull out the description value
return ((DescriptionAttribute)attributes[0]).Description;
}
}
return name;
}

I've seen this done where I would put
MyStringEnum.Foo.ToString();
In this case it would give "A"

The cleanest solution for this problem is to create a custom attribute that will store the string value you want for the enum constant. I've used that strategy in the past and it worked out fairly well. Here's a blog post detailing the work involved:
Enum With String Values In C# - Stefan Sedich's Blog
Of course this is only necessary if you need some kind of meaningful text. If the name of the enum constant works for you...then you can simply call ToString().

Related

DataAnnotations: read out the Name property in code

I have decorated the following enum with Display DataAnnotation attributes:
public enum RequiredOptions
{
[Display(Name="Optional",Description ="Optional")]
Optional,
[Display(Name="Not Used",Description ="Not Used")]
NotUsed,
[Display(Name="Required",Description ="Required")]
Required
}
I'd like to read out the Name value of the Display attribute for a given enum value in my code. How do I do this?
public static string DisplayRequiredOptionName(RequiredOptions opt)
{
// Return the value of Name from the display attribute from opt
}
Well, after doing some digging in the MVC source code (see src\System.Web.Mvc\Html\SelectExtensions.cs, see GetDisplayName()), here's what I got to work:
public static string GetEnumDisplayName<T>(T enumInstance)
{
return GetDisplayName(enumInstance.GetType().GetField(enumInstance.ToString()));
}
private static string GetDisplayName(FieldInfo field)
{
DisplayAttribute display = field.GetCustomAttribute<DisplayAttribute>(inherit: false);
if (display != null)
{
string name = display.GetName();
if (!String.IsNullOrEmpty(name))
{
return name;
}
}
return field.Name;
}

Read values from a non-delimited string into class object

I have a string with the following structure:
Student Name________AgeAddress_______________________Bithday___Lvl
Example:
Jonh Smith 016Some place in NY, USA 01/01/2014L01
As you can see, there is no delimited character like | or ,
Also, there is no space between fields (if you check, there is no space between Age/Address and Birthday/Level.
The size of each field is static so if data's length is less then it will contains white spaces.
I have a class that need to be filled with that information:
public class StudentData
{
public char[] _name = new char[20];
public string name;
public char[] _age = new char[3];
public string age;
public char[] _address = new char[30];
public string address;
public char[] _bday = new char[10];
public string bday;
public char[] _level = new char[3];
public string level;
}
Is there any way to do this automatically and dynamically?
I mean I really don't want to code like this:
myClass.name = stringLine.substring(0,19);
myClass.age = stringLine.substring(20,22);
That's because I have way more fields that the ones added in this example & way more string lines with other different data.
Update: There were supposed to be a lot of spaces between "Smith" and "016", but I don't know how to edit it.
Update2: If I use StringReader.Read() I can evade to use substring and indexes, but it isn't still so dynamically because I would need to repeat those 3 lines for each field.
StringReader reader = new StringReader(stringLine);
reader.Read(myClass._name, 0 myClass._name.Length);
myClass.name = new string(myClass._name);
Given your requirement I came up with an interesting solution. All be-it it may be more complex and longer than using the String.SubString() method as stated.
However this solution is transferable to other types and other string. I used a concept of Attributes, Properties, and Reflection to parse a string by a Fixed Length and setting the class Properties.
Note I did change your StudentData class to follow a more conventional coding style. Following this handy guide on MSDN: http://msdn.microsoft.com/en-us/library/xzf533w0(v=vs.71).aspx
Here is the new StudentData class. Note it uses the properties as opposed to fields. (Not discussed here).
public class StudentData
{
string name;
string age;
string address;
string bday;
string level;
[FixedLengthDelimeter(0, 20)]
public string Name { get { return this.name; } set { this.name = value; } }
[FixedLengthDelimeter(1, 3)]
public string Age { get { return this.age; } set { this.age = value; } }
[FixedLengthDelimeter(2, 30)]
public string Address { get { return this.address; } set { this.address = value; } }
[FixedLengthDelimeter(3, 10)]
public string BDay { get { return this.bday; } set { this.bday = value; } }
[FixedLengthDelimeter(4, 3)]
public string Level { get { return this.level; } set { this.level = value; } }
}
Note on each of the properties there is an Attribute called FixedLengthDelimeter that takes two parameters.
OrderNumber
FixedLength
The OrderNumber parameter denotes the order in the string (not the position) but the order in which we process from the string. The second parameter denotes the Length of the string when parsing the string. Here is the full attribute class.
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public sealed class FixedLengthDelimeterAttribute : Attribute
{
public FixedLengthDelimeterAttribute(int orderNumber, int fixedLength)
{
this.fixedLength = fixedLength;
this.orderNumber = orderNumber;
}
readonly int fixedLength;
readonly int orderNumber;
public int FixedLength { get { return this.fixedLength; } }
public int OrderNumber { get { return this.orderNumber; } }
}
Now the attribute is simple enough. Accepts the two paramters we discussed eariler in the constructor.
Finally there is another method to parse the string into the object type such as.
public static class FixedLengthFormatter
{
public static T ParseString<T>(string inputString)
{
Type tType = typeof(T);
var properties = tType.GetProperties(BindingFlags.Instance | BindingFlags.Public); //;.Where(x => x.GetCustomAttributes(typeof(FixedLengthDelimeterAttribute), false).Count() > 0);
T newT = (T)Activator.CreateInstance(tType);
Dictionary<PropertyInfo, FixedLengthDelimeterAttribute> dictionary = new Dictionary<PropertyInfo, FixedLengthDelimeterAttribute>();
foreach (var property in properties)
{
var atts = property.GetCustomAttributes(typeof(FixedLengthDelimeterAttribute), false);
if (atts.Length == 0)
continue;
dictionary[property] = atts[0] as FixedLengthDelimeterAttribute;
}
foreach (var kvp in dictionary.OrderBy(x => x.Value.OrderNumber))
{
int length = kvp.Value.FixedLength;
if (inputString.Length < length)
throw new Exception("error on attribute order number:" + kvp.Value.OrderNumber + " the string is too short.");
string piece = inputString.Substring(0, length);
inputString = inputString.Substring(length);
kvp.Key.SetValue(newT, piece.Trim(), null);
}
return newT;
}
}
The method above is what does the string parsing. It is a pretty basic utility that reads all the properties that have the FixedLengthDelimeter attribute applied a Dictionary. That dictionary is then enumerated (ordered by OrderNumber) and then calling the SubString() method twice on the input string.
The first substring is to parse the next Token while the second substring resets the inputString to start processing the next token.
Finally as it is parsing the string it is then applying the parsed string to the property of the class Type provided to the method.
Now this can be used simply like this:
string data1 = "Jonh Smith 016Some place in NY, USA 01/01/2014L01";
StudentData student = FixedLengthFormatter.ParseString<StudentData>(data1);
What this does:
Parses a string against property attributes in a fixed length format.
What this does not do:
It does convert the parsed strings to another type. Therefore all the properties must be a string. (this can be easily adapted by adding some type casting logic in).
It is not well tested. This is only tested against a few samples.
It is not by all means the only or best solution out there.
You could use FileHelpers library (NuGet).
Just define the structure of your input file with attributes:
[FixedLengthRecord]
public class StudentData
{
[FieldFixedLength(20)]
[FieldTrim(TrimMode.Right)]
public string name;
[FieldFixedLength(3)]
public string age;
[FieldFixedLength(30)]
[FieldTrim(TrimMode.Right)]
public string address;
[FieldFixedLength(10)]
public string bday;
[FieldFixedLength(3)]
public string level;
}
Then simply read the file using FileHelperEngine<T>:
var engine = new FileHelperEngine<StudentData>();
var students = engine.ReadFile(filename);

Get value from string in IEnumerable

I have the following code
public const string boy = "B";
public const string girl = "G";
private gender(string description, string value)
{
Description = description;
Value = value;
}
public static IEnumerable<gender> GetAll()
{
yield return new gender("Boy", boy);
yield return new gender("Girl", girl);
}
I want to find a way to give my program the string "Boy" and get as a result the string "B" as it should. How is this possible?
var param = "Boy";
var someBoy = GetAll().Where(g => g.Description == param).Select(g => g.Value).Single();
Almost the same as in prevois answer but with check for wrong value received :)
var rez = GetAll().FirstOrDefault(g=>g.Description==string_received);
if(rez==null) throw new ArgumentException();
return rez.Value;
Why do you even want to use an IEnumerable method and a Gender class? You should use an Enum in this situation. Define your Enum like this:
public Enum Gender { Boy, Girl };
Then, you can do this:
Gender gender = Gender.Boy;
string description = gender.ToString();
// If you want to use 'B' as value...
string value = description[0];
Read more about enums here: http://www.dotnetperls.com/enum

forcing a variable to hold certain values only

I am using vs 2012. I have a simple string property
string _someString;
public string MyString
{
get
{
return _someString;
}
}
I want this property to hold only certain values. So that when the client uses this property only those certain values can be used.
It sounds like what you really want is an enum:
public enum MyValues //TODO rename all the things
{
SomeValue,
SomeOtherValue,
FinalValue,
}
Then your property can be:
private MyValues value;
public MyValues MyValue
{
get { return value; }
}
If you need to get a string representation of that value just call ToString on the enum value:
string stringValue = value.ToString();
Use an enum as in :
enum MyEnum
{
AllowableValue#1,
AllowableValue#2,
...
}
public MyEnum myEnum { get; set; }
Then populate some UI element with only the values of the enum.
I suppose you want to have some validation on the setter then:
public string MyString
{
get
{
return _someString;
}
set
{
if (value == "a" || value == "b" /* ... */)
_someString = value;
else
throw new InvalidArgumentException("Invalid value!");
}
}
Make sure to set it via the property, not the actual member variable.

Add a space in this string between words [duplicate]

This question already has answers here:
Enum ToString with user friendly strings
(25 answers)
Using [Display(Name = "X")] with an enum. Custom HtmlHelper in MVC3 ASP.Net
(3 answers)
Closed 9 years ago.
Tried setting up an enum that has spaces in attributes but was very hard so figured their might be an easy way to hack this with a string format or something since their is only one enum that I need that has spaces and I know exactly what it is. Any helping wiht adding a space to this string
public class Address
{
...blah...more class datatypes here...
public AddressType Type { get; set; } //AddressType is an enum
...blah....
}
if (Address.Type.ToString() == "UnitedStates")
{
**Add space between United and States**
}
If your enum entries are in camel case, you can insert a whitespace before the upper letter
string res = Regex.Replace("UnitedStates", "[A-Z]", " $0").Trim();
You can create your own ToString method on the enumeration using an extension method.
public static class AddressTypeExtensions
{
public static string ToMyString(this AddressType addressType)
{
if (addressType == AddressType.UnitedStates)
return "United States";
return addressType.ToString();
}
}
This is a neat trick I found yesterday (in 2009). I wonder why I never thought of it myself. In the .net framework there is no way how to control .ToString() for enumerations. To work around that an extension method can be created as well as an attribute to decorate the different values of the enumeration. Then we can write something like this:
public enum TestEnum
{
[EnumString("Value One")]
Value1,
[EnumString("Value Two")]
Value2,
[EnumString("Value Three")]
Value3
}
EnumTest test = EnumTest.Value1;
Console.Write(test.ToStringEx());
The code to accomplish this is pretty simple:
[AttributeUsage(AttributeTargets.Field)]
public class EnumStringAttribute : Attribute
{
private string enumString;
public EnumStringAttribute(string EnumString)
{
enumString = EnumString;
}
public override string ToString()
{
return enumString;
}
}
public static class ExtensionMethods
{
public static string ToStringEx(this Enum enumeration)
{
Type type = enumeration.GetType();
FieldInfo field = type.GetField(enumeration.ToString());
var enumString =
(from attribute in field.GetCustomAttributes(true)
where attribute is EnumStringAttribute
select attribute).FirstOrDefault();
if (enumString != null)
return enumString.ToString();
// otherwise...
return enumeration.ToString();
}
}
[TestMethod()]
public void ToStringTest()
{
Assert.AreEqual("Value One", TestEnum.Value1.ToStringEx());
Assert.AreEqual("Value Two", TestEnum.Value2.ToStringEx());
Assert.AreEqual("Value Three", TestEnum.Value3.ToStringEx());
}
The credit goes to this post.
I have a handy Extension method for exactly this
public static class EnumExtensions
{
public static string ToNonPascalString(this Enum enu)
{
return Regex.Replace(enu.ToString(), "([A-Z])", " $1").Trim();
}
public T EnumFromString<T>(string value) where T : struct
{
string noSpace = value.Replace(" ", "");
if (Enum.GetNames(typeof(T)).Any(x => x.ToString().Equals(noSpace)))
{
return (T)Enum.Parse(typeof(T), noSpace);
}
return default(T);
}
}
Example:
public enum Test
{
UnitedStates,
NewZealand
}
// from enum to string
string result = Test.UnitedStates.ToNonPascalString(); // United States
// from string to enum
Test myEnum = EnumExtensions.EnumFromString<Test>("New Zealand"); // NewZealand
The following code will convert AbcDefGhi to Abc Def Ghi.
public static string ConvertEnum(this string value)
{
string result = string.Empty;
char[] letters = value.ToCharArray();
foreach (char c in letters)
if (c.ToString() != c.ToString().ToLower())
result += " " + c;
else
result += c.ToString();
return result;
}

Categories

Resources