WPF application settings - resetting a single property - c#

There is a way to reset application settings with Settings.Default.Reset()
Is there a way to reset only one property? Something like
Settings.Default.Properties["MyPropertyName"].Reset();

You can use the Settings.Default.Properties["MyProperty"].DefaultValue to obtain the default value for the property, and set the property value to that.

It's the PropertyValue that's need to be set in combinaison of Deserialized (the order matter) :
public void ResetOneSetting(string propertyName)
{
SettingsPropertyValue propertyToReset = Settings.Default.PropertyValues.OfType<SettingsPropertyValue>().FirstOrDefault(p => p.Name == propertyName);
if (propertyToReset != null)
{
propertyToReset.PropertyValue = propertyToReset.Property.DefaultValue;
propertyToReset.Deserialized = false;
}
}

Found solution when reading .NET source code:
Settings.Default.PropertyValues["MyPropertyName"].SerializedValue = Settings.Default.Properties["MyPropertyName"].DefaultValue;
Settings.Default.PropertyValues["MyPropertyName"].Deserialized = false;

In my case (.NET Framework 4.6.1, with a System.Drawing.Color as setting), I also had to re-assign the value in Settings.Default, otherwise the change seemed to be ignored:
var propertyValue = Settings.Default.PropertyValues["myPropertyName"];
propertyValue.PropertyValue = propertyValue.Property.DefaultValue;
propertyValue.Deserialized = false;
Settings.Default["myPropertyName"] = propertyValue.PropertyValue;

I use the following code to reset a setting in my program. It takes advantage of reflection and allows you to pass a property directly instead of you manually writing out a properties name. It can be used like ResetToDefaultValue(TestSettings.Default, x => x.TextFieldStuff);
The advantage of this is that it does not all your settings are in Settings but some might be stored in different settings files.
//Way to use
//ResetToDefaultValue(TestSettings.Default, x => x.TextFieldStuff);
private static void ResetToDefaultValue<T1, T2>(T1 settings, Expression<Func<T1, T2>> property, bool saveOnReset = true)
{
if (IsSameOrSubclass(typeof(ApplicationSettingsBase), settings.GetType()))
{
ApplicationSettingsBase s = settings as ApplicationSettingsBase;
if (s != null)
{
MemberInfo member = GetMemberInfo(property);
if (!s.PropertyValues[member.Name].UsingDefaultValue)
{
s.PropertyValues[member.Name].PropertyValue = s.PropertyValues[member.Name].Property.DefaultValue;
s.PropertyValues[member.Name].Deserialized = false;
s[member.Name] = s.PropertyValues[member.Name].PropertyValue; //Triggers the property changed
if (saveOnReset)
{
s.Save();
}
}
}
}
}
//Way to use
//GetMemberInfo((TestSettings testSettings) => testSettings.TextFieldStuff);
private static MemberInfo GetMemberInfo<T1, T2>(Expression<Func<T1, T2>> expression)
{
if (IsSameOrSubclass(typeof(MemberExpression), expression.Body.GetType()))
{
MemberExpression member = (MemberExpression)expression.Body;
return member.Member;
}
throw new ArgumentException(#"Expression is not a member access", nameof(expression));
}
private static bool IsSameOrSubclass(Type potentialBase, Type potentialDescendant)
{
return potentialDescendant.IsSubclassOf(potentialBase)
|| potentialDescendant == potentialBase;
}
Or if you are using C# 7.1 or greater, you can use feature matching.
//Way to use
//ResetToDefaultValue(TestSettings.Default, x => x.TextFieldStuff);
private static void ResetToDefaultValue<T1, T2>(T1 settings, Expression<Func<T1, T2>> property, bool saveOnReset = true)
{
//Requires C# >= 7.1
if (settings is ApplicationSettingsBase s)
{
MemberInfo member = GetMemberInfo(property);
if (!s.PropertyValues[member.Name].UsingDefaultValue)
{
s.PropertyValues[member.Name].PropertyValue = s.PropertyValues[member.Name].Property.DefaultValue;
s.PropertyValues[member.Name].Deserialized = false;
s[member.Name] = s.PropertyValues[member.Name].PropertyValue;
if (saveOnReset)
{
s.Save();
}
}
}
}
//Way to use
//GetMemberInfo((TestSettings testSettings) => testSettings.TextFieldStuff);
private static MemberInfo GetMemberInfo<T1, T2>(Expression<Func<T1, T2>> expression)
{
//Requires C# >= 7.0
if (expression.Body is MemberExpression member)
{
return member.Member;
}
throw new ArgumentException(#"Expression is not a member access", nameof(expression));
}

While I checked out the answers from #dalleria and #nikita, I run into the problem that
the PropertyValue (SettingsPropertyValue) got defaulted unexpectely when I tried to get a deep copy of DefaultValue (SettingsProperty) or PropertyValue (SettingsPropertyValue) or any other same typed value.
So here is my short implementation of a deep copy function that is part of a class, so I apologize for not refactoring it to a extension or tool method.
private SettingsPropertyValue settingsPropertyValue; // (ex. Settings.Default.PropertyValues["anyPropertyName"])
private SettingsProperty settingsProperty
=> settingsPropertyValue.Property;
/// <summary>
/// Create a deep copy of <paramref name="value"/>.
/// </summary>
/// <param name="value">
/// Should be a deserialized value (ex. <see cref="SettingsPropertyValue.PropertyValue"/>)
/// or a serialized value (ex. <see cref="SettingsProperty.DefaultValue"/>).
/// </param>
/// <param name="isDeserialized">Indicates whether <paramref name="value"/> is deserialized or serialized.</param>
private PropertyType copyValue<PropertyType>(object value, bool isDeserialized)
{
var temporaryPropertyValue = settingsPropertyValue.PropertyValue;
settingsPropertyValue.PropertyValue = value;
if (isDeserialized)
// We have to reassign, otherwise PropertyValue/SerializedValue of SettingsPropertyValue may be defaulted
settingsPropertyValue.SerializedValue = settingsPropertyValue.SerializedValue;
settingsPropertyValue.Deserialized = false;
var propertyValue = (PropertyType)settingsPropertyValue.PropertyValue;
settingsPropertyValue.PropertyValue = temporaryPropertyValue;
return propertyValue;
}
You can then reset a single property of an instance of ApplicationSettings/SettingsBase with these lines:
SettingsBase settings; // (ex. Settings.Default)
public void SetOriginalFromDefault()
{
object defaultValue = settingsProperty.DefaultValue;
defaultValue = copyValue(defaultValue, false);
// We want to set the new value. It also triggers the INotifyPropertyChanged of settings, if the instance is from type ApplicationSettings
settings[settingsProperty.Name] = defaultValue;
}

Related

How to get default value for runtime object [duplicate]

I'm using reflection to loop through a Type's properties and set certain types to their default. Now, I could do a switch on the type and set the default(Type) explicitly, but I'd rather do it in one line. Is there a programmatic equivalent of default?
In case of a value type use Activator.CreateInstance and it should work fine.
When using reference type just return null
public static object GetDefault(Type type)
{
if(type.IsValueType)
{
return Activator.CreateInstance(type);
}
return null;
}
In the newer version of .net such as .net standard, type.IsValueType needs to be written as type.GetTypeInfo().IsValueType
Why not call the method that returns default(T) with reflection ? You can use GetDefault of any type with:
public object GetDefault(Type t)
{
return this.GetType().GetMethod("GetDefaultGeneric").MakeGenericMethod(t).Invoke(this, null);
}
public T GetDefaultGeneric<T>()
{
return default(T);
}
You can use PropertyInfo.SetValue(obj, null). If called on a value type it will give you the default. This behavior is documented in .NET 4.0 and in .NET 4.5.
If you're using .NET 4.0 or above and you want a programmatic version that isn't a codification of rules defined outside of code, you can create an Expression, compile and run it on-the-fly.
The following extension method will take a Type and get the value returned from default(T) through the Default method on the Expression class:
public static T GetDefaultValue<T>()
{
// We want an Func<T> which returns the default.
// Create that expression here.
Expression<Func<T>> e = Expression.Lambda<Func<T>>(
// The default value, always get what the *code* tells us.
Expression.Default(typeof(T))
);
// Compile and return the value.
return e.Compile()();
}
public static object GetDefaultValue(this Type type)
{
// Validate parameters.
if (type == null) throw new ArgumentNullException("type");
// We want an Func<object> which returns the default.
// Create that expression here.
Expression<Func<object>> e = Expression.Lambda<Func<object>>(
// Have to convert to object.
Expression.Convert(
// The default value, always get what the *code* tells us.
Expression.Default(type), typeof(object)
)
);
// Compile and return the value.
return e.Compile()();
}
You should also cache the above value based on the Type, but be aware if you're calling this for a large number of Type instances, and don't use it constantly, the memory consumed by the cache might outweigh the benefits.
Why do you say generics are out of the picture?
public static object GetDefault(Type t)
{
Func<object> f = GetDefault<object>;
return f.Method.GetGenericMethodDefinition().MakeGenericMethod(t).Invoke(null, null);
}
private static T GetDefault<T>()
{
return default(T);
}
This is optimized Flem's solution:
using System.Collections.Concurrent;
namespace System
{
public static class TypeExtension
{
//a thread-safe way to hold default instances created at run-time
private static ConcurrentDictionary<Type, object> typeDefaults =
new ConcurrentDictionary<Type, object>();
public static object GetDefaultValue(this Type type)
{
return type.IsValueType
? typeDefaults.GetOrAdd(type, Activator.CreateInstance)
: null;
}
}
}
The chosen answer is a good answer, but be careful with the object returned.
string test = null;
string test2 = "";
if (test is string)
Console.WriteLine("This will never be hit.");
if (test2 is string)
Console.WriteLine("Always hit.");
Extrapolating...
string test = GetDefault(typeof(string));
if (test is string)
Console.WriteLine("This will never be hit.");
I do the same task like this.
//in MessageHeader
private void SetValuesDefault()
{
MessageHeader header = this;
Framework.ObjectPropertyHelper.SetPropertiesToDefault<MessageHeader>(this);
}
//in ObjectPropertyHelper
public static void SetPropertiesToDefault<T>(T obj)
{
Type objectType = typeof(T);
System.Reflection.PropertyInfo [] props = objectType.GetProperties();
foreach (System.Reflection.PropertyInfo property in props)
{
if (property.CanWrite)
{
string propertyName = property.Name;
Type propertyType = property.PropertyType;
object value = TypeHelper.DefaultForType(propertyType);
property.SetValue(obj, value, null);
}
}
}
//in TypeHelper
public static object DefaultForType(Type targetType)
{
return targetType.IsValueType ? Activator.CreateInstance(targetType) : null;
}
Equivalent to Dror's answer but as an extension method:
namespace System
{
public static class TypeExtensions
{
public static object Default(this Type type)
{
object output = null;
if (type.IsValueType)
{
output = Activator.CreateInstance(type);
}
return output;
}
}
}
The Expressions can help here:
private static Dictionary<Type, Delegate> lambdasMap = new Dictionary<Type, Delegate>();
private object GetTypedNull(Type type)
{
Delegate func;
if (!lambdasMap.TryGetValue(type, out func))
{
var body = Expression.Default(type);
var lambda = Expression.Lambda(body);
func = lambda.Compile();
lambdasMap[type] = func;
}
return func.DynamicInvoke();
}
I did not test this snippet, but i think it should produce "typed" nulls for reference types..
Slight adjustments to #Rob Fonseca-Ensor's solution: The following extension method also works on .Net Standard since I use GetRuntimeMethod instead of GetMethod.
public static class TypeExtensions
{
public static object GetDefault(this Type t)
{
var defaultValue = typeof(TypeExtensions)
.GetRuntimeMethod(nameof(GetDefaultGeneric), new Type[] { })
.MakeGenericMethod(t).Invoke(null, null);
return defaultValue;
}
public static T GetDefaultGeneric<T>()
{
return default(T);
}
}
...and the according unit test for those who care about quality:
[Fact]
public void GetDefaultTest()
{
// Arrange
var type = typeof(DateTime);
// Act
var defaultValue = type.GetDefault();
// Assert
defaultValue.Should().Be(default(DateTime));
}
/// <summary>
/// returns the default value of a specified type
/// </summary>
/// <param name="type"></param>
public static object GetDefault(this Type type)
{
return type.IsValueType ? (!type.IsGenericType ? Activator.CreateInstance(type) : type.GenericTypeArguments[0].GetDefault() ) : null;
}
This should work:
Nullable<T> a = new Nullable<T>().GetValueOrDefault();
If you already create an object, you can try...
var yourObj = new yourObj();
var properties = yourObj.GetType().GetProperties();
foreach (var p in properties)
{
// you can get default value for each property
var defaultValue = p.GetValue(yourObj, null);
}

Dll Private method throw "not accesible due to access level" WITHIN owner class

I'm an amateur and not English native speaker. I'm trying to do mapper for use it with Dapper's dynamic results, I need it for a personal project and I couldn't adapt self Dapper mapper either Automapper to my needs (probably due to my lack of knowledge), so I decided to make mine.
It works flawlessly when I add the mapper code with "Add -> Existing Item", but if I try to use it as a DLL it throws the "not accessible due to access level" exception, pointing this part of the code:
public T Map(IEnumerable<dynamic> dapperResult, bool cleanResult = false)
{
var parser = new PrePostFixesParser(this);
T mapped = this.NewObject(dapperResult.First()); <------//EXCEPTION HERE
if (_OnlyConstructor.Contains(this.TType)) return mapped;
//... Other things
The method NewObject:
private T NewObject(dynamic dyn)
{
Type t = typeof(T);
bool IsInterfaceNotIEnumerable = t.IsInterface
&& !typeof(IDictionary).IsAssignableFrom(t)
&& !(typeof(IEnumerable).IsAssignableFrom(t) && !typeof(string).IsAssignableFrom(t));
if (IsInterfaceNotIEnumerable)
throw new CustomException_DapperMapper(
#"DapperMapper.NewObject: Exception trying to instantiate an interface that isn't an IEnumerable. This is a BUG.");
T newObj;
//if there are a constructor configurated
if (_Constructors.ContainsKey(this.TType))
{
//object[] constructorParams = GetConstructorParams();
try
{
Func<dynamic, T> constDelegate = (Func<dynamic, T>)_Constructors[this.TType];
newObj = constDelegate(dyn);
}
catch (Exception err)
{
throw new CustomException_DapperMapper(
$#"DapperMapper.NewObject: Exception using constructor to create object of type {TType.Name} with delegate {_Constructors[TType]}.", err);
}
}
//if there are no constructor configurated, use parameterless constructor
else newObj = Activator.CreateInstance<T>();
return newObj;
}
Both methods are part of the same class called DapperMapper. I've read the page always want all the possible code in the same question, so I'm posting the entire class here, but it's a large one, so I'm posting too the link to Github where I have all the solution... just in case:
public class DapperMapper<T> : DMStatic_Mapper, iDapperMapper
{
public DapperMapper(MapperStore store)
{
this.TType = typeof(T);
this.MappersStore = store;
this.MappersStore.StoreMapper(this.TType, this);
}
#region properties
public MapperStore MappersStore { get; private set; }
public Dictionary<MemberInfo, MemberTypeInfo> mtInfos { get { return _mtInfos[this.TType]; } }
public Type TType { get; private set; }
public IEnumerable<string> NamesList { get { return _NamesList[this.TType]; } }
public Tuple<string[], bool> Prefixes { get { return _Prefixes.ContainsKey(this.TType) ? _Prefixes[this.TType] : null; } }
public Tuple<string[], bool> Postfixes { get { return _Postfixes.ContainsKey(this.TType) ? _Postfixes[this.TType] : null; } }
#endregion
#region helpers
private T NewObject(dynamic dyn)
{
Type t = typeof(T);
bool IsInterfaceNotIEnumerable = t.IsInterface
&& !typeof(IDictionary).IsAssignableFrom(t)
&& !(typeof(IEnumerable).IsAssignableFrom(t) && !typeof(string).IsAssignableFrom(t));
if (IsInterfaceNotIEnumerable)
throw new CustomException_DapperMapper(
#"DapperMapper.NewObject: Exception trying to instantiate an interface that isn't an IEnumerable. This is a BUG.");
T newObj;
//if there are a constructor configurated
if (_Constructors.ContainsKey(this.TType))
{
//object[] constructorParams = GetConstructorParams();
try
{
Func<dynamic, T> constDelegate = (Func<dynamic, T>)_Constructors[this.TType];
newObj = constDelegate(dyn);
}
catch (Exception err)
{
throw new CustomException_DapperMapper(
$#"DapperMapper.NewObject: Exception using constructor to create object of type {TType.Name}
with delegate {_Constructors[TType]}.", err);
}
}
//if there are no constructor configurated, use parameterless constructor
else newObj = Activator.CreateInstance<T>();
return newObj;
}
#endregion
#region public methods
/// <summary>
/// Remove duplicated results due to JOINs.
/// </summary>
/// <param name="origDapperResult"></param>
/// <param name="cleanResult"></param>
/// <returns></returns>
public IEnumerable<dynamic> GetDistinctDapperResult(IEnumerable<dynamic> origDapperResult, bool cleanResult)
{
PrePostFixesParser parser = new PrePostFixesParser(this);
IEnumerable<string> names = this.NamesList;
List<dynamic> result = new List<dynamic>();
foreach(dynamic dyn in origDapperResult)
{
IDictionary<string, object> dict =
(!cleanResult ? parser.GetTypeMembersWithoutPrePostFixes(dyn, names) : dyn)
as IDictionary<string, object>;
bool distinct = true;
foreach(dynamic resultDyn in result)
{
IDictionary<string, object> resDict = resultDyn as IDictionary<string, object>;
if(dict.Keys.SequenceEqual(resDict.Keys) && dict.Values.SequenceEqual(resDict.Values))
{
distinct = false;
break;
}
}
if (distinct) result.Add(dyn);
}
return result;
}
/// <summary>
/// Check if the dynamic object have all the members needed to map a new T object, except those setted as IEnumerable,
/// which should be provided in others dynamic.
/// </summary>
/// <param name="dyn"></param>
/// <returns></returns>
public bool CheckIfDynamicHasAllTypeMembersByName(dynamic dyn)
{
IDictionary<string, object> membersDict = dyn as IDictionary<string, object>;
IEnumerable<string> dynList = membersDict.Select(kvp => kvp.Key);
PrePostFixesParser parser = new PrePostFixesParser(this);
IEnumerable<string> list = parser.GetCleanNamesList(this.NamesList);
return !dynList.Except(list).Any() && !list.Except(dynList).Any();
}
/// <summary>
/// Check if the dynamic object have all the members needed to map a new T object, except those setted as IEnumerable,
/// which should be provided in others dynamic.
/// </summary>
/// <param name="membersDict"></param>
/// <returns></returns>
public bool CheckIfDynamicHasAllTypeMembersByName(IDictionary<string, object> membersDict)
{
IEnumerable<string> dynList = membersDict.Select(kvp => kvp.Key);
PrePostFixesParser parser = new PrePostFixesParser(this);
return dynList.SequenceEqual(parser.GetCleanNamesList(this.NamesList));
}
/// <summary>
/// Generic Map.
/// </summary>
/// <param name="dapperResult"></param>
/// <returns></returns>
public T Map(IEnumerable<dynamic> dapperResult, bool cleanResult = false)
{
var parser = new PrePostFixesParser(this);
T mapped = this.NewObject(dapperResult.First());
if (_OnlyConstructor.Contains(this.TType)) return mapped;
//TODO: divide el siguiente foreach en dos con dos nuevos diccionarios estáticos, uno para pInfos y otro para fInfos,
//aunque se repita código: hacer métodos para cada parte del código del tipo:
//private T PreMapCreator(KeyValuePair<PropertyInfo, MemberTypeInfo> kvp, IEnumerable<dynamic> dapperResult, bool cleanResult = false)
//private T PreMapIEnumerable(KeyValuePair<PropertyInfo, MemberTypeInfo> kvp, IEnumerable<dynamic> dapperResult, bool cleanResult = false)
//...
//Loop through all members
foreach (KeyValuePair<MemberInfo, MemberTypeInfo> kvp in mtInfos)
{
if (kvp.Value == MemberTypeInfo.Ignore)
continue;
//Member have a creator
else if ((kvp.Value & MemberTypeInfo.Creator) == MemberTypeInfo.Creator)
{
//MemberDelegate mDel = (MemberDelegate)_MembersCreators[this.TType][kvp.Key.Name];
Func<dynamic, object> mDel = (Func<dynamic, object>)_MembersCreators[this.TType][kvp.Key.Name];
if (kvp.Key.MemberType == MemberTypes.Property) ((PropertyInfo)kvp.Key).SetValue(mapped, mDel(dapperResult));
else ((FieldInfo)kvp.Key).SetValue(mapped, mDel(dapperResult));
}
//Member is IDictionary or IEnumerable
else if ((kvp.Value & MemberTypeInfo.IEnumerable) == MemberTypeInfo.IEnumerable)
{
Type t = GetMemberType(kvp.Key);
//if ((kvp.Value & MemberTypeInfo.Interface) == MemberTypeInfo.Interface) t = ResolveInterface(kvp.Key, dapperResult);
//else t = GetMemberType(kvp.Key);
/*
{
//Type of property or field
if (kvp.Key.MemberType == MemberTypes.Property) t = ((PropertyInfo)kvp.Key).PropertyType;
else t = ((FieldInfo)kvp.Key).FieldType;
}*/
bool isAnInterface = (kvp.Value & MemberTypeInfo.Interface) == MemberTypeInfo.Interface;
bool isNested = (kvp.Value & MemberTypeInfo.Nested) == MemberTypeInfo.Nested;
//If member is a dictionary
if (typeof(IDictionary).IsAssignableFrom(t))
{
//Create a dummy dictionary with the dapper's dynamic result which should be equal to the final one
DictionaryMapper dictMapper = new DictionaryMapper(dapperResult, kvp.Key.Name, isNested, isAnInterface, cleanResult, t, this);
try
{
if (kvp.Key.MemberType == MemberTypes.Property) ((PropertyInfo)kvp.Key).SetValue(mapped, dictMapper.DummyDictionary);
else ((FieldInfo)kvp.Key).SetValue(mapped, dictMapper.DummyDictionary);
}
catch (Exception err)
{
throw new CustomException_DapperMapper(
$#"DapperMapper.Map: Couldn't map IDictionary member {kvp.Key.Name} with value contained by dynamic object.
Incorrect type of value?: {kvp.Value.ToString()}",
err);
}
}
//Rest of enumerables
else
{
IEnumerable<dynamic> iEnumDapperResult;
//Select current member's values from dynamic
if (isNested && !cleanResult)
{
//Type mType = t; // GetMemberType(kvp.Key);//IEnumerable<T>
Type genericType = t.GenericTypeArguments[0];//mType.GenericTypeArguments[0];//T
if ((kvp.Value & MemberTypeInfo.Interface) == MemberTypeInfo.Interface)
{
bool genericIsInterfaceNotIEnumerable =
genericType.IsInterface &&
!typeof(IDictionary).IsAssignableFrom(genericType) &&
!(typeof(IEnumerable).IsAssignableFrom(genericType) && !typeof(string).IsAssignableFrom(genericType));
if (genericIsInterfaceNotIEnumerable) genericType = ResolveInterface(genericType, dapperResult);
}
iDapperMapper nestedMapper = MappersStore.GetMapper(genericType);
var nestedParser = new PrePostFixesParser(nestedMapper);
iEnumDapperResult = dapperResult
.Select(dyn => nestedParser.GetTypeMembersWithoutPrePostFixes(dyn, nestedMapper.NamesList));
}
else if (!cleanResult) iEnumDapperResult = dapperResult.Select(dyn => parser.RemovePrePostFixesFromDictionary(dyn));
else iEnumDapperResult = dapperResult;
//Create dummy IEnumerable
EnumerableMapper enumMapper = new EnumerableMapper(iEnumDapperResult, kvp.Key.Name, isNested, t, this.TType); ;
var dummy = Activator.CreateInstance(t, enumMapper.DummyEnumerable);
try
{
if (kvp.Key.MemberType == MemberTypes.Property) ((PropertyInfo)kvp.Key).SetValue(mapped, dummy);
else ((FieldInfo)kvp.Key).SetValue(mapped, dummy);
}
catch (Exception err)
{
throw new CustomException_DapperMapper(
$#"DapperMapper.Map: Couldn't map IEnumerable member {kvp.Key.Name} with value contained by dynamic object.
Incorrect type of value?: {kvp.Value.ToString()}",
err);
}
}
}//End IDictionary/IEnumerable
//If Built-in
else if ((kvp.Value & MemberTypeInfo.BuiltIn) == MemberTypeInfo.BuiltIn)
{
string name = parser.RemoveFieldsUnderscore(kvp.Key.Name);
IDictionary<string, object> dapperDict;
if (!cleanResult)
dapperDict = parser.GetTypeMembersWithoutPrePostFixes(dapperResult.First(), NamesList) as IDictionary<string, object>;
else
dapperDict = dapperResult.First() as IDictionary<string, object>;
if (!dapperDict.ContainsKey(name))
throw new CustomException_DapperMapper(
$#"DapperMapper.Map: There's no member in dynamic dapper result with name {kvp.Key.Name}. Cannot Map object.");
try
{
if (kvp.Key.MemberType == MemberTypes.Property) ((PropertyInfo)kvp.Key).SetValue(mapped, dapperDict[name]);
else ((FieldInfo)kvp.Key).SetValue(mapped, dapperDict[name]);
}
catch (Exception err)
{
throw new CustomException_DapperMapper(
$#"DapperMapper.Map: Couldn't map BuiltIn-type member {kvp.Key.Name} with value contained by dynamic object.
Incorrect type of value?: {kvp.Value.ToString()}",
err);
}
}
//if nested
else if ((kvp.Value & MemberTypeInfo.Nested) == MemberTypeInfo.Nested)
{
Type mType = GetMemberType(kvp.Key);
if ((kvp.Value & MemberTypeInfo.Interface) == MemberTypeInfo.Interface)
mType = ResolveInterface(mType, dapperResult);
//access generic Map method through nongeneric interface method
iDapperMapper nestedMapper = MappersStore.GetMapper(mType);
if (nestedMapper == null)
throw new CustomException_DapperMapper(
$#"DapperMapper.Map: No Mapper found at store for property {kvp.Key.Name} of type {mType.ToString()}.
If you want to map a nested property you have to create a mapper for that property type.");
if (kvp.Key.MemberType == MemberTypes.Property)
((PropertyInfo)kvp.Key).SetValue(mapped, nestedMapper.NoGenericMap(dapperResult, cleanResult));
else ((FieldInfo)kvp.Key).SetValue(mapped, nestedMapper.NoGenericMap(dapperResult, cleanResult));
}
}
return mapped;
}
/// <summary>
/// Generic map to IEnumerables. Result HAVE to be ordered by the splitOn column.
/// </summary>
/// <typeparam name="R"></typeparam>
/// <param name="dapperResult"></param>
/// <param name="splitOn"></param>
/// <param name="cleanResult"></param>
/// <returns></returns>
public R Map<R>(IEnumerable<dynamic> dapperResult, string splitOn = "Id", bool cleanResult = false)
where R : IEnumerable<T>
{
R result;
Type r = typeof(R);
List<dynamic> singleObjectDynamic = new List<dynamic>();
object splitObject = (dapperResult.First() as IDictionary<string, object>)[splitOn];
if (typeof(IList).IsAssignableFrom(r))
{
result = (R)Activator.CreateInstance(typeof(List<>).MakeGenericType(this.TType));
foreach (dynamic dyn in dapperResult)
{
IDictionary<string, object> dict = dyn as IDictionary<string, object>;
if (!dict.ContainsKey(splitOn))
throw new CustomException_DapperMapper(
$#"DapperMapper.Map(IEnumerable): Dapper result doesn't have a member with name equals to splitOn parameter.
SplitOn = {splitOn}");
if (!object.Equals(splitObject, dict[splitOn]) || dapperResult.Last() == dyn)
{
((IList)result).Add(Map(singleObjectDynamic));
singleObjectDynamic.Clear();
splitObject = dict[splitOn];
}
else
singleObjectDynamic.Add(dyn);
}
}
else
{
//http://stackoverflow.com/questions/18251587/assign-any-ienumerable-to-object-property
var addMethod = r.GetMethod("Add", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
// Property doesn't support Adding
if (addMethod == null)
throw new CustomException_DapperMapper(
$#"DapperMapper.Map(IEnumerable): Method Add doesn't exist in enumerable type to map.
enumType: {r.Name}.");
if (r.IsGenericTypeDefinition) result = (R)Activator.CreateInstance(r.MakeGenericType(this.TType));
else result = (R)Activator.CreateInstance(r);
foreach (dynamic dyn in dapperResult)
{
IDictionary<string, object> dict = dyn as IDictionary<string, object>;
if (!dict.ContainsKey(splitOn))
throw new CustomException_DapperMapper(
$#"DapperMapper.Map(IEnumerable): Dapper result doesn't have a member with name equals to splitOn parameter.
SplitOn = {splitOn}");
if (!object.Equals(splitObject, dict[splitOn]) || dapperResult.Last() == dyn)
{
addMethod.Invoke(result, new object[] { NoGenericMap(dyn) });
singleObjectDynamic.Clear();
splitObject = dict[splitOn];
}
else
singleObjectDynamic.Add(dyn);
}
}
return result;
}
/// <summary>
/// Non-generic Map.
/// </summary>
/// <param name="dapperResult"></param>
/// <returns></returns>
public object NoGenericMap(dynamic dapperResult, bool cleanResult = false)
{
IEnumerable<dynamic> ienum = new List<dynamic>() { dapperResult } as IEnumerable<dynamic>;
return this.Map(ienum, cleanResult);
}
/// <summary>
/// Non-generic Map.
/// </summary>
/// <param name="dapperResult"></param>
/// <param name="cleanResult"></param>
/// <returns></returns>
public object NoGenericMap(IEnumerable<dynamic> dapperResult, bool cleanResult = false)
{
return this.Map(dapperResult, cleanResult);
}
#endregion
}
QUESTION
So, what's happening?
I'm astonished by this one. Am I terribly wrong or class's methods should be able to see same class private methods?
For the DLL I just began it with a new Class Library project in visual studio 2015 community, and when done build it with the typical release configuration, then I went to a console project I'm using to testing it (I just made a simple database there, to have direct Dapper's dynamic results objects to test it) and added reference to the DLL. Could it be that I build the DLL wrong? Do I have to do something more in the testing project apart from referencing the DLL and add the corresponding using namespace?
I've tried searching for private methods, DLLs, private methods in DLLs, private methods in the public class in DLLs, but it seems I'm not able to find anything that solves it. Apart from checking the class and method have the proper access keywords (c# default access is private if no other is specified, right?), and clean, build, rebuild again both solutions, I don't see anymore.
I'm afraid I'm just forgetting something stupid, but it works if I copy-paste the code (or add it with "Add->Existing Item" as I said before") instead of using the DLL, therefore the code is correct, right?
EDIT:
Due to comment of GSerg I'm adding the way I call DapperMapper in the testing project after adding the reference to the DLL:
MapperStore store = new MapperStore();
DapperMapper<Persons> mapper = (DapperMapper<Persons>)store.GetMapper(typeof(Persons));
Persons p = mapper.Map(result);
EDIT2:
As can be seen in the comments, as suggested by GSerg I created a new console project for testing, add the reference to the DLL, copy-paste ONLY the test (mock classes, database), hit F5 and got the same result. I double checked that I builded the DLL and the test project at release mode, and use windows explorer to confirm that there were no DLL's .cs files at the testing project.

How to find out if a property value has been set to the default value for it's type in C# [duplicate]

I'm using reflection to loop through a Type's properties and set certain types to their default. Now, I could do a switch on the type and set the default(Type) explicitly, but I'd rather do it in one line. Is there a programmatic equivalent of default?
In case of a value type use Activator.CreateInstance and it should work fine.
When using reference type just return null
public static object GetDefault(Type type)
{
if(type.IsValueType)
{
return Activator.CreateInstance(type);
}
return null;
}
In the newer version of .net such as .net standard, type.IsValueType needs to be written as type.GetTypeInfo().IsValueType
Why not call the method that returns default(T) with reflection ? You can use GetDefault of any type with:
public object GetDefault(Type t)
{
return this.GetType().GetMethod("GetDefaultGeneric").MakeGenericMethod(t).Invoke(this, null);
}
public T GetDefaultGeneric<T>()
{
return default(T);
}
You can use PropertyInfo.SetValue(obj, null). If called on a value type it will give you the default. This behavior is documented in .NET 4.0 and in .NET 4.5.
If you're using .NET 4.0 or above and you want a programmatic version that isn't a codification of rules defined outside of code, you can create an Expression, compile and run it on-the-fly.
The following extension method will take a Type and get the value returned from default(T) through the Default method on the Expression class:
public static T GetDefaultValue<T>()
{
// We want an Func<T> which returns the default.
// Create that expression here.
Expression<Func<T>> e = Expression.Lambda<Func<T>>(
// The default value, always get what the *code* tells us.
Expression.Default(typeof(T))
);
// Compile and return the value.
return e.Compile()();
}
public static object GetDefaultValue(this Type type)
{
// Validate parameters.
if (type == null) throw new ArgumentNullException("type");
// We want an Func<object> which returns the default.
// Create that expression here.
Expression<Func<object>> e = Expression.Lambda<Func<object>>(
// Have to convert to object.
Expression.Convert(
// The default value, always get what the *code* tells us.
Expression.Default(type), typeof(object)
)
);
// Compile and return the value.
return e.Compile()();
}
You should also cache the above value based on the Type, but be aware if you're calling this for a large number of Type instances, and don't use it constantly, the memory consumed by the cache might outweigh the benefits.
Why do you say generics are out of the picture?
public static object GetDefault(Type t)
{
Func<object> f = GetDefault<object>;
return f.Method.GetGenericMethodDefinition().MakeGenericMethod(t).Invoke(null, null);
}
private static T GetDefault<T>()
{
return default(T);
}
This is optimized Flem's solution:
using System.Collections.Concurrent;
namespace System
{
public static class TypeExtension
{
//a thread-safe way to hold default instances created at run-time
private static ConcurrentDictionary<Type, object> typeDefaults =
new ConcurrentDictionary<Type, object>();
public static object GetDefaultValue(this Type type)
{
return type.IsValueType
? typeDefaults.GetOrAdd(type, Activator.CreateInstance)
: null;
}
}
}
The chosen answer is a good answer, but be careful with the object returned.
string test = null;
string test2 = "";
if (test is string)
Console.WriteLine("This will never be hit.");
if (test2 is string)
Console.WriteLine("Always hit.");
Extrapolating...
string test = GetDefault(typeof(string));
if (test is string)
Console.WriteLine("This will never be hit.");
I do the same task like this.
//in MessageHeader
private void SetValuesDefault()
{
MessageHeader header = this;
Framework.ObjectPropertyHelper.SetPropertiesToDefault<MessageHeader>(this);
}
//in ObjectPropertyHelper
public static void SetPropertiesToDefault<T>(T obj)
{
Type objectType = typeof(T);
System.Reflection.PropertyInfo [] props = objectType.GetProperties();
foreach (System.Reflection.PropertyInfo property in props)
{
if (property.CanWrite)
{
string propertyName = property.Name;
Type propertyType = property.PropertyType;
object value = TypeHelper.DefaultForType(propertyType);
property.SetValue(obj, value, null);
}
}
}
//in TypeHelper
public static object DefaultForType(Type targetType)
{
return targetType.IsValueType ? Activator.CreateInstance(targetType) : null;
}
Equivalent to Dror's answer but as an extension method:
namespace System
{
public static class TypeExtensions
{
public static object Default(this Type type)
{
object output = null;
if (type.IsValueType)
{
output = Activator.CreateInstance(type);
}
return output;
}
}
}
The Expressions can help here:
private static Dictionary<Type, Delegate> lambdasMap = new Dictionary<Type, Delegate>();
private object GetTypedNull(Type type)
{
Delegate func;
if (!lambdasMap.TryGetValue(type, out func))
{
var body = Expression.Default(type);
var lambda = Expression.Lambda(body);
func = lambda.Compile();
lambdasMap[type] = func;
}
return func.DynamicInvoke();
}
I did not test this snippet, but i think it should produce "typed" nulls for reference types..
Slight adjustments to #Rob Fonseca-Ensor's solution: The following extension method also works on .Net Standard since I use GetRuntimeMethod instead of GetMethod.
public static class TypeExtensions
{
public static object GetDefault(this Type t)
{
var defaultValue = typeof(TypeExtensions)
.GetRuntimeMethod(nameof(GetDefaultGeneric), new Type[] { })
.MakeGenericMethod(t).Invoke(null, null);
return defaultValue;
}
public static T GetDefaultGeneric<T>()
{
return default(T);
}
}
...and the according unit test for those who care about quality:
[Fact]
public void GetDefaultTest()
{
// Arrange
var type = typeof(DateTime);
// Act
var defaultValue = type.GetDefault();
// Assert
defaultValue.Should().Be(default(DateTime));
}
/// <summary>
/// returns the default value of a specified type
/// </summary>
/// <param name="type"></param>
public static object GetDefault(this Type type)
{
return type.IsValueType ? (!type.IsGenericType ? Activator.CreateInstance(type) : type.GenericTypeArguments[0].GetDefault() ) : null;
}
This should work:
Nullable<T> a = new Nullable<T>().GetValueOrDefault();
If you already create an object, you can try...
var yourObj = new yourObj();
var properties = yourObj.GetType().GetProperties();
foreach (var p in properties)
{
// you can get default value for each property
var defaultValue = p.GetValue(yourObj, null);
}

Get name of property as a string

(See below solution I created using the answer I accepted)
I'm trying to improve the maintainability of some code involving reflection. The app has a .NET Remoting interface exposing (among other things) a method called Execute for accessing parts of the app not included in its published remote interface.
Here is how the app designates properties (a static one in this example) which are meant to be accessible via Execute:
RemoteMgr.ExposeProperty("SomeSecret", typeof(SomeClass), "SomeProperty");
So a remote user could call:
string response = remoteObject.Execute("SomeSecret");
and the app would use reflection to find SomeClass.SomeProperty and return its value as a string.
Unfortunately, if someone renames SomeProperty and forgets to change the 3rd parm of ExposeProperty(), it breaks this mechanism.
I need to the equivalent of:
SomeClass.SomeProperty.GetTheNameOfThisPropertyAsAString()
to use as the 3rd parm in ExposeProperty so refactoring tools would take care of renames.
Is there a way to do this?
Okay, here's what I ended up creating (based upon the answer I selected and the question he referenced):
// <summary>
// Get the name of a static or instance property from a property access lambda.
// </summary>
// <typeparam name="T">Type of the property</typeparam>
// <param name="propertyLambda">lambda expression of the form: '() => Class.Property' or '() => object.Property'</param>
// <returns>The name of the property</returns>
public string GetPropertyName<T>(Expression<Func<T>> propertyLambda)
{
var me = propertyLambda.Body as MemberExpression;
if (me == null)
{
throw new ArgumentException("You must pass a lambda of the form: '() => Class.Property' or '() => object.Property'");
}
return me.Member.Name;
}
Usage:
// Static Property
string name = GetPropertyName(() => SomeClass.SomeProperty);
// Instance Property
string name = GetPropertyName(() => someObject.SomeProperty);
Now with this cool capability, it's time to simplify the ExposeProperty method. Polishing doorknobs is dangerous work...
With C# 6.0, this is now a non-issue as you can do:
nameof(SomeProperty)
This expression is resolved at compile-time to "SomeProperty".
MSDN documentation of nameof.
Using GetMemberInfo from here: Retrieving Property name from lambda expression you can do something like this:
RemoteMgr.ExposeProperty(() => SomeClass.SomeProperty)
public class SomeClass
{
public static string SomeProperty
{
get { return "Foo"; }
}
}
public class RemoteMgr
{
public static void ExposeProperty<T>(Expression<Func<T>> property)
{
var expression = GetMemberInfo(property);
string path = string.Concat(expression.Member.DeclaringType.FullName,
".", expression.Member.Name);
// Do ExposeProperty work here...
}
}
public class Program
{
public static void Main()
{
RemoteMgr.ExposeProperty("SomeSecret", () => SomeClass.SomeProperty);
}
}
Okay, here's what I ended up creating (based upon the answer I selected and the question he referenced):
// <summary>
// Get the name of a static or instance property from a property access lambda.
// </summary>
// <typeparam name="T">Type of the property</typeparam>
// <param name="propertyLambda">lambda expression of the form: '() => Class.Property' or '() => object.Property'</param>
// <returns>The name of the property</returns>
public string GetPropertyName<T>(Expression<Func<T>> propertyLambda)
{
var me = propertyLambda.Body as MemberExpression;
if (me == null)
{
throw new ArgumentException("You must pass a lambda of the form: '() => Class.Property' or '() => object.Property'");
}
return me.Member.Name;
}
Usage:
// Static Property
string name = GetPropertyName(() => SomeClass.SomeProperty);
// Instance Property
string name = GetPropertyName(() => someObject.SomeProperty);
There's a well-known hack to extract it from lambda expression (this is from the PropertyObserver class, by Josh Smith, in his MVVM foundation):
private static string GetPropertyName<TPropertySource>
(Expression<Func<TPropertySource, object>> expression)
{
var lambda = expression as LambdaExpression;
MemberExpression memberExpression;
if (lambda.Body is UnaryExpression)
{
var unaryExpression = lambda.Body as UnaryExpression;
memberExpression = unaryExpression.Operand as MemberExpression;
}
else
{
memberExpression = lambda.Body as MemberExpression;
}
Debug.Assert(memberExpression != null,
"Please provide a lambda expression like 'n => n.PropertyName'");
if (memberExpression != null)
{
var propertyInfo = memberExpression.Member as PropertyInfo;
return propertyInfo.Name;
}
return null;
}
Sorry, this was missing some context. This was part of a larger class where TPropertySource is the class containing the property. You could make the function generic in TPropertySource to extract it from the class. I recommend taking a look at the full code from the MVVM Foundation.
The PropertyInfo class should help you achieve this, if I understand correctly.
Type.GetProperties() method
PropertyInfo[] propInfos = typeof(ReflectedType).GetProperties();
propInfos.ToList().ForEach(p =>
Console.WriteLine(string.Format("Property name: {0}", p.Name));
Is this what you need?
You can use Reflection to obtain the actual names of the properties.
http://www.csharp-examples.net/reflection-property-names/
If you need a way to assign a "String Name" to a property, why don't you write an attribute that you can reflect over to get the string name?
[StringName("MyStringName")]
private string MyProperty
{
get { ... }
}
I modified your solution to chain over multiple properties:
public static string GetPropertyName<T>(Expression<Func<T>> propertyLambda)
{
MemberExpression me = propertyLambda.Body as MemberExpression;
if (me == null)
{
throw new ArgumentException("You must pass a lambda of the form: '() => Class.Property' or '() => object.Property'");
}
string result = string.Empty;
do
{
result = me.Member.Name + "." + result;
me = me.Expression as MemberExpression;
} while (me != null);
result = result.Remove(result.Length - 1); // remove the trailing "."
return result;
}
Usage:
string name = GetPropertyName(() => someObject.SomeProperty.SomeOtherProperty);
// returns "SomeProperty.SomeOtherProperty"
Old question, but another answer to this question is to create a static function in a helper class that uses the CallerMemberNameAttribute.
public static string GetPropertyName([CallerMemberName] String propertyName = null) {
return propertyName;
}
And then use it like:
public string MyProperty {
get { Console.WriteLine("{0} was called", GetPropertyName()); return _myProperty; }
}
Based on the answer which is already in the question and on this article: https://handcraftsman.wordpress.com/2008/11/11/how-to-get-c-property-names-without-magic-strings/ I am presenting my solution to this problem:
public static class PropertyNameHelper
{
/// <summary>
/// A static method to get the Propertyname String of a Property
/// It eliminates the need for "Magic Strings" and assures type safety when renaming properties.
/// See: http://stackoverflow.com/questions/2820660/get-name-of-property-as-a-string
/// </summary>
/// <example>
/// // Static Property
/// string name = PropertyNameHelper.GetPropertyName(() => SomeClass.SomeProperty);
/// // Instance Property
/// string name = PropertyNameHelper.GetPropertyName(() => someObject.SomeProperty);
/// </example>
/// <typeparam name="T"></typeparam>
/// <param name="propertyLambda"></param>
/// <returns></returns>
public static string GetPropertyName<T>(Expression<Func<T>> propertyLambda)
{
var me = propertyLambda.Body as MemberExpression;
if (me == null)
{
throw new ArgumentException("You must pass a lambda of the form: '() => Class.Property' or '() => object.Property'");
}
return me.Member.Name;
}
/// <summary>
/// Another way to get Instance Property names as strings.
/// With this method you don't need to create a instance first.
/// See the example.
/// See: https://handcraftsman.wordpress.com/2008/11/11/how-to-get-c-property-names-without-magic-strings/
/// </summary>
/// <example>
/// string name = PropertyNameHelper((Firma f) => f.Firmenumsatz_Waehrung);
/// </example>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TReturn"></typeparam>
/// <param name="expression"></param>
/// <returns></returns>
public static string GetPropertyName<T, TReturn>(Expression<Func<T, TReturn>> expression)
{
MemberExpression body = (MemberExpression)expression.Body;
return body.Member.Name;
}
}
And a Test which also shows the usage for instance and static properties:
[TestClass]
public class PropertyNameHelperTest
{
private class TestClass
{
public static string StaticString { get; set; }
public string InstanceString { get; set; }
}
[TestMethod]
public void TestGetPropertyName()
{
Assert.AreEqual("StaticString", PropertyNameHelper.GetPropertyName(() => TestClass.StaticString));
Assert.AreEqual("InstanceString", PropertyNameHelper.GetPropertyName((TestClass t) => t.InstanceString));
}
}
You can use the StackTrace class to get the name of the current function, (or if you put the code in a function, then step down a level and get the calling function).
See http://msdn.microsoft.com/en-us/library/system.diagnostics.stacktrace(VS.71).aspx
I've been using this answer to great effect: Get the property, as a string, from an Expression<Func<TModel,TProperty>>
I realize I already answered this question a while back. The only advantage my other answer has is that it works for static properties. I find the syntax in this answer much more useful because you don't have to create a variable of the type you want to reflect.
I had some difficulty using the solutions already suggested for my specific use case, but figured it out eventually. I don't think my specific case is worthy of a new question, so I am posting my solution here for reference. (This is very closely related to the question and provides a solution for anyone else with a similar case to mine).
The code I ended up with looks like this:
public class HideableControl<T>: Control where T: class
{
private string _propertyName;
private PropertyInfo _propertyInfo;
public string PropertyName
{
get { return _propertyName; }
set
{
_propertyName = value;
_propertyInfo = typeof(T).GetProperty(value);
}
}
protected override bool GetIsVisible(IRenderContext context)
{
if (_propertyInfo == null)
return false;
var model = context.Get<T>();
if (model == null)
return false;
return (bool)_propertyInfo.GetValue(model, null);
}
protected void SetIsVisibleProperty(Expression<Func<T, bool>> propertyLambda)
{
var expression = propertyLambda.Body as MemberExpression;
if (expression == null)
throw new ArgumentException("You must pass a lambda of the form: 'vm => vm.Property'");
PropertyName = expression.Member.Name;
}
}
public interface ICompanyViewModel
{
string CompanyName { get; }
bool IsVisible { get; }
}
public class CompanyControl: HideableControl<ICompanyViewModel>
{
public CompanyControl()
{
SetIsVisibleProperty(vm => vm.IsVisible);
}
}
The important part for me is that in the CompanyControl class the compiler will only allow me to choose a boolean property of ICompanyViewModel which makes it easier for other developers to get it right.
The main difference between my solution and the accepted answer is that my class is generic and I only want to match properties from the generic type that are boolean.
it's how I implemented it , the reason behind is if the class that you want to get the name from it's member is not static then you need to create an instanse of that and then get the member's name. so generic here comes to help
public static string GetName<TClass>(Expression<Func<TClass, object>> exp)
{
MemberExpression body = exp.Body as MemberExpression;
if (body == null)
{
UnaryExpression ubody = (UnaryExpression)exp.Body;
body = ubody.Operand as MemberExpression;
}
return body.Member.Name;
}
the usage is like this
var label = ClassExtension.GetName<SomeClass>(x => x.Label); //x is refering to 'SomeClass'

String representation of an Enum

I have the following enumeration:
public enum AuthenticationMethod
{
FORMS = 1,
WINDOWSAUTHENTICATION = 2,
SINGLESIGNON = 3
}
The problem however is that I need the word "FORMS" when I ask for AuthenticationMethod.FORMS and not the id 1.
I have found the following solution for this problem (link):
First I need to create a custom attribute called "StringValue":
public class StringValue : System.Attribute
{
private readonly string _value;
public StringValue(string value)
{
_value = value;
}
public string Value
{
get { return _value; }
}
}
Then I can add this attribute to my enumerator:
public enum AuthenticationMethod
{
[StringValue("FORMS")]
FORMS = 1,
[StringValue("WINDOWS")]
WINDOWSAUTHENTICATION = 2,
[StringValue("SSO")]
SINGLESIGNON = 3
}
And of course I need something to retrieve that StringValue:
public static class StringEnum
{
public static string GetStringValue(Enum value)
{
string output = null;
Type type = value.GetType();
//Check first in our cached results...
//Look for our 'StringValueAttribute'
//in the field's custom attributes
FieldInfo fi = type.GetField(value.ToString());
StringValue[] attrs =
fi.GetCustomAttributes(typeof(StringValue),
false) as StringValue[];
if (attrs.Length > 0)
{
output = attrs[0].Value;
}
return output;
}
}
Good now I've got the tools to get a string value for an enumerator.
I can then use it like this:
string valueOfAuthenticationMethod = StringEnum.GetStringValue(AuthenticationMethod.FORMS);
Okay now all of these work like a charm but I find it a whole lot of work. I was wondering if there is a better solution for this.
I also tried something with a dictionary and static properties but that wasn't better either.
Try type-safe-enum pattern.
public sealed class AuthenticationMethod {
private readonly String name;
private readonly int value;
public static readonly AuthenticationMethod FORMS = new AuthenticationMethod (1, "FORMS");
public static readonly AuthenticationMethod WINDOWSAUTHENTICATION = new AuthenticationMethod (2, "WINDOWS");
public static readonly AuthenticationMethod SINGLESIGNON = new AuthenticationMethod (3, "SSN");
private AuthenticationMethod(int value, String name){
this.name = name;
this.value = value;
}
public override String ToString(){
return name;
}
}
Update
Explicit (or implicit) type conversion can be done by
adding static field with mapping
private static readonly Dictionary<string, AuthenticationMethod> instance = new Dictionary<string,AuthenticationMethod>();
n.b. In order that the initialisation of the the "enum member" fields doesn't throw a NullReferenceException when calling the instance constructor, be sure to put the Dictionary field before the "enum member" fields in your class. This is because static field initialisers are called in declaration order, and before the static constructor, creating the weird and necessary but confusing situation that the instance constructor can be called before all static fields have been initialised, and before the static constructor is called.
filling this mapping in instance constructor
instance[name] = this;
and adding user-defined type conversion operator
public static explicit operator AuthenticationMethod(string str)
{
AuthenticationMethod result;
if (instance.TryGetValue(str, out result))
return result;
else
throw new InvalidCastException();
}
Use method
Enum.GetName(Type MyEnumType, object enumvariable)
as in (Assume Shipper is a defined Enum)
Shipper x = Shipper.FederalExpress;
string s = Enum.GetName(typeof(Shipper), x);
There are a bunch of other static methods on the Enum class worth investigating too...
You can reference the name rather than the value by using ToString()
Console.WriteLine("Auth method: {0}", AuthenticationMethod.Forms.ToString());
The documentation is here:
http://msdn.microsoft.com/en-us/library/16c1xs4z.aspx
...and if you name your enums in Pascal Case (as I do - such as ThisIsMyEnumValue = 1 etc.) then you could use a very simple regex to print the friendly form:
static string ToFriendlyCase(this string EnumString)
{
return Regex.Replace(EnumString, "(?!^)([A-Z])", " $1");
}
which can easily be called from any string:
Console.WriteLine("ConvertMyCrazyPascalCaseSentenceToFriendlyCase".ToFriendlyCase());
Outputs:
Convert My Crazy Pascal Case Sentence To Friendly Case
That saves running all the way around the houses creating custom attributes and attaching them to your enums or using lookup tables to marry an enum value with a friendly string and best of all it's self managing and can be used on any Pascal Case string which is infinitely more reusable. Of course, it doesn't allow you to have a different friendly name than your enum which your solution does provide.
I do like your original solution though for more complex scenarios though. You could take your solution one step further and make your GetStringValue an extension method of your enum and then you wouldn't need to reference it like StringEnum.GetStringValue...
public static string GetStringValue(this AuthenticationMethod value)
{
string output = null;
Type type = value.GetType();
FieldInfo fi = type.GetField(value.ToString());
StringValue[] attrs = fi.GetCustomAttributes(typeof(StringValue), false) as StringValue[];
if (attrs.Length > 0)
output = attrs[0].Value;
return output;
}
You could then access it easily straight from your enum instance:
Console.WriteLine(AuthenticationMethod.SSO.GetStringValue());
Unfortunately reflection to get attributes on enums is quite slow:
See this question: Anyone know a quick way to get to custom attributes on an enum value?
The .ToString() is quite slow on enums too.
You can write extension methods for enums though:
public static string GetName( this MyEnum input ) {
switch ( input ) {
case MyEnum.WINDOWSAUTHENTICATION:
return "Windows";
//and so on
}
}
This isn't great, but will be quick and not require the reflection for attributes or field name.
C#6 Update
If you can use C#6 then the new nameof operator works for enums, so nameof(MyEnum.WINDOWSAUTHENTICATION) will be converted to "WINDOWSAUTHENTICATION" at compile time, making it the quickest way to get enum names.
Note that this will convert the explicit enum to an inlined constant, so it doesn't work for enums that you have in a variable. So:
nameof(AuthenticationMethod.FORMS) == "FORMS"
But...
var myMethod = AuthenticationMethod.FORMS;
nameof(myMethod) == "myMethod"
I use an extension method:
public static class AttributesHelperExtension
{
public static string ToDescription(this Enum value)
{
var da = (DescriptionAttribute[])(value.GetType().GetField(value.ToString())).GetCustomAttributes(typeof(DescriptionAttribute), false);
return da.Length > 0 ? da[0].Description : value.ToString();
}
}
Now decorate the enum with:
public enum AuthenticationMethod
{
[Description("FORMS")]
FORMS = 1,
[Description("WINDOWSAUTHENTICATION")]
WINDOWSAUTHENTICATION = 2,
[Description("SINGLESIGNON ")]
SINGLESIGNON = 3
}
When you call
AuthenticationMethod.FORMS.ToDescription() you will get "FORMS".
Just use the ToString() method
public enum any{Tomato=0,Melon,Watermelon}
To reference the string Tomato, just use
any.Tomato.ToString();
Very simple solution to this with .Net 4.0 and above. No other code is needed.
public enum MyStatus
{
Active = 1,
Archived = 2
}
To get the string about just use:
MyStatus.Active.ToString("f");
or
MyStatus.Archived.ToString("f");`
The value will be "Active" or "Archived".
To see the different string formats (the "f" from above) when calling Enum.ToString see this Enumeration Format Strings page
I use the Description attribute from the System.ComponentModel namespace. Simply decorate the enum and then use this code to retrieve it:
public static string GetDescription<T>(this object enumerationValue)
where T : struct
{
Type type = enumerationValue.GetType();
if (!type.IsEnum)
{
throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue");
}
//Tries to find a DescriptionAttribute for a potential friendly name
//for the enum
MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString());
if (memberInfo != null && memberInfo.Length > 0)
{
object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attrs != null && attrs.Length > 0)
{
//Pull out the description value
return ((DescriptionAttribute)attrs[0]).Description;
}
}
//If we have no description attribute, just return the ToString of the enum
return enumerationValue.ToString();
}
As an example:
public enum Cycle : int
{
[Description("Daily Cycle")]
Daily = 1,
Weekly,
Monthly
}
This code nicely caters for enums where you don't need a "Friendly name" and will return just the .ToString() of the enum.
I really like Jakub Šturc's answer, but it's shortcoming is that you cannot use it with a switch-case statement. Here's a slightly modified version of his answer that can be used with a switch statement:
public sealed class AuthenticationMethod
{
#region This code never needs to change.
private readonly string _name;
public readonly Values Value;
private AuthenticationMethod(Values value, String name){
this._name = name;
this.Value = value;
}
public override String ToString(){
return _name;
}
#endregion
public enum Values
{
Forms = 1,
Windows = 2,
SSN = 3
}
public static readonly AuthenticationMethod FORMS = new AuthenticationMethod (Values.Forms, "FORMS");
public static readonly AuthenticationMethod WINDOWSAUTHENTICATION = new AuthenticationMethod (Values.Windows, "WINDOWS");
public static readonly AuthenticationMethod SINGLESIGNON = new AuthenticationMethod (Values.SSN, "SSN");
}
So you get all of the benefits of Jakub Šturc's answer, plus we can use it with a switch statement like so:
var authenticationMethodVariable = AuthenticationMethod.FORMS; // Set the "enum" value we want to use.
var methodName = authenticationMethodVariable.ToString(); // Get the user-friendly "name" of the "enum" value.
// Perform logic based on which "enum" value was chosen.
switch (authenticationMethodVariable.Value)
{
case authenticationMethodVariable.Values.Forms: // Do something
break;
case authenticationMethodVariable.Values.Windows: // Do something
break;
case authenticationMethodVariable.Values.SSN: // Do something
break;
}
I use a combination of several of the suggestions above, combined with some caching. Now, I got the idea from some code that I found somewhere on the net, but I can neither remember where I got it or find it. So if anyone ever finds something that looks similar please comment with the attribution.
Anyway, the usage involves the type converters, so if you are binding to the UI it 'just works'. You can extended with Jakub's pattern for quick code lookup by initializing from the type converter into the static methods.
The base usage would look like this
[TypeConverter(typeof(CustomEnumTypeConverter<MyEnum>))]
public enum MyEnum
{
// The custom type converter will use the description attribute
[Description("A custom description")]
ValueWithCustomDescription,
// This will be exposed exactly.
Exact
}
The code for the custom enum type converter follows:
public class CustomEnumTypeConverter<T> : EnumConverter
where T : struct
{
private static readonly Dictionary<T,string> s_toString =
new Dictionary<T, string>();
private static readonly Dictionary<string, T> s_toValue =
new Dictionary<string, T>();
private static bool s_isInitialized;
static CustomEnumTypeConverter()
{
System.Diagnostics.Debug.Assert(typeof(T).IsEnum,
"The custom enum class must be used with an enum type.");
}
public CustomEnumTypeConverter() : base(typeof(T))
{
if (!s_isInitialized)
{
Initialize();
s_isInitialized = true;
}
}
protected void Initialize()
{
foreach (T item in Enum.GetValues(typeof(T)))
{
string description = GetDescription(item);
s_toString[item] = description;
s_toValue[description] = item;
}
}
private static string GetDescription(T optionValue)
{
var optionDescription = optionValue.ToString();
var optionInfo = typeof(T).GetField(optionDescription);
if (Attribute.IsDefined(optionInfo, typeof(DescriptionAttribute)))
{
var attribute =
(DescriptionAttribute)Attribute.
GetCustomAttribute(optionInfo, typeof(DescriptionAttribute));
return attribute.Description;
}
return optionDescription;
}
public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture,
object value, Type destinationType)
{
var optionValue = (T)value;
if (destinationType == typeof(string) &&
s_toString.ContainsKey(optionValue))
{
return s_toString[optionValue];
}
return base.ConvertTo(context, culture, value, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value)
{
var stringValue = value as string;
if (!string.IsNullOrEmpty(stringValue) && s_toValue.ContainsKey(stringValue))
{
return s_toValue[stringValue];
}
return base.ConvertFrom(context, culture, value);
}
}
}
In your question you never said that you actually need the numeric value of the enum anywhere.
If you do not and just need an enum of type string (which is not an integral type so can not be a base of enum) here is a way:
static class AuthenticationMethod
{
public static readonly string
FORMS = "Forms",
WINDOWSAUTHENTICATION = "WindowsAuthentication";
}
you can use the same syntax as enum to reference it
if (bla == AuthenticationMethod.FORMS)
It will be a bit slower than with numeric values (comparing strings instead of numbers) but on the plus side it is not using reflection (slow) to access the string.
Update: Visiting this page, 8 years later, after not touching C# for a long while, looks like my answer is no longer the best solution. I really like the converter solution tied with attribute-functions.
If you are reading this, please make sure you also check out other answers. (hint: they are above this one)
As most of you, I really liked the selected answer by Jakub Šturc, but I also really hate to copy-paste code, and try to do it as little as I can.
So I decided I wanted an EnumBase class from which most of the functionality is inherited/built-in, leaving me to focus on the content instead of behavior.
The main problem with this approach is based on the fact that although Enum values are type-safe instances, the interaction is with the Static implementation of the Enum Class type.
So with a little help of generics magic, I think I finally got the correct mix.
Hope someone finds this as useful as I did.
I'll start with Jakub's example, but using inheritance and generics:
public sealed class AuthenticationMethod : EnumBase<AuthenticationMethod, int>
{
public static readonly AuthenticationMethod FORMS =
new AuthenticationMethod(1, "FORMS");
public static readonly AuthenticationMethod WINDOWSAUTHENTICATION =
new AuthenticationMethod(2, "WINDOWS");
public static readonly AuthenticationMethod SINGLESIGNON =
new AuthenticationMethod(3, "SSN");
private AuthenticationMethod(int Value, String Name)
: base( Value, Name ) { }
public new static IEnumerable<AuthenticationMethod> All
{ get { return EnumBase<AuthenticationMethod, int>.All; } }
public static explicit operator AuthenticationMethod(string str)
{ return Parse(str); }
}
And here is the base class:
using System;
using System.Collections.Generic;
using System.Linq; // for the .AsEnumerable() method call
// E is the derived type-safe-enum class
// - this allows all static members to be truly unique to the specific
// derived class
public class EnumBase<E, T> where E: EnumBase<E, T>
{
#region Instance code
public T Value { get; private set; }
public string Name { get; private set; }
protected EnumBase(T EnumValue, string Name)
{
Value = EnumValue;
this.Name = Name;
mapping.Add(Name, this);
}
public override string ToString() { return Name; }
#endregion
#region Static tools
static private readonly Dictionary<string, EnumBase<E, T>> mapping;
static EnumBase() { mapping = new Dictionary<string, EnumBase<E, T>>(); }
protected static E Parse(string name)
{
EnumBase<E, T> result;
if (mapping.TryGetValue(name, out result))
{
return (E)result;
}
throw new InvalidCastException();
}
// This is protected to force the child class to expose it's own static
// method.
// By recreating this static method at the derived class, static
// initialization will be explicit, promising the mapping dictionary
// will never be empty when this method is called.
protected static IEnumerable<E> All
{ get { return mapping.Values.AsEnumerable().Cast<E>(); } }
#endregion
}
How I solved this as an extension method:
using System.ComponentModel;
public static string GetDescription(this Enum value)
{
var descriptionAttribute = (DescriptionAttribute)value.GetType()
.GetField(value.ToString())
.GetCustomAttributes(false)
.Where(a => a is DescriptionAttribute)
.FirstOrDefault();
return descriptionAttribute != null ? descriptionAttribute.Description : value.ToString();
}
Enum:
public enum OrderType
{
None = 0,
[Description("New Card")]
NewCard = 1,
[Description("Reload")]
Refill = 2
}
Usage (where o.OrderType is a property with the same name as the enum):
o.OrderType.GetDescription()
Which gives me a string of "New Card" or "Reload" instead of the actual enum value NewCard and Refill.
If you've come here looking to implement a simple "Enum" but whose values are strings instead of ints, here is the simplest solution:
public sealed class MetricValueList
{
public static readonly string Brand = "A4082457-D467-E111-98DC-0026B9010912";
public static readonly string Name = "B5B5E167-D467-E111-98DC-0026B9010912";
}
Implementation:
var someStringVariable = MetricValueList.Brand;
I agree with Keith, but I can't vote up (yet).
I use a static method and swith statement to return exactly what I want. In the database I store tinyint and my code only uses the actual enum, so the strings are for UI requirements. After numerous testing this resulted in the best performance and most control over the output.
public static string ToSimpleString(this enum)
{
switch (enum)
{
case ComplexForms:
return "ComplexForms";
break;
}
}
public static string ToFormattedString(this enum)
{
switch (enum)
{
case ComplexForms:
return "Complex Forms";
break;
}
}
However, by some accounts, this leads to a possible maintenance nightmare and some code smell. I try to keep an eye for enums that are long and a lot of enums, or those that change frequently. Otherwise, this has been a great solution for me.
When I'm confronted with this problem, there are a couple of questions that I try to find the answers to first:
Are the names of my enum values sufficiently friendly for the purpose, or do I need to provide friendlier ones?
Do I need to round-trip? That is, will I need to take text values and parse them into enum values?
Is this something I need to do for many enums in my project, or just one?
What kind of UI elements will I be presenting this information in - in particular, will I be binding to the UI, or using property sheets?
Does this need to be localizable?
The simplest way to do this is with Enum.GetValue (and support round-tripping using Enum.Parse). It's also often worth building a TypeConverter, as Steve Mitcham suggests, to support UI binding. (It's not necessary to build a TypeConverter when you're using property sheets, which is one of the nice things about property sheets. Though lord knows they have their own issues.)
In general, if the answers to the above questions suggest that's not going to work, my next step is to create and populate a static Dictionary<MyEnum, string>, or possibly a Dictionary<Type, Dictionary<int, string>>. I tend to skip the intermediate decorate-the-code-with-attributes step because what's usually coming down the pike next is the need to change the friendly values after deployment (often, but not always, because of localization).
I created a base class for creating string-valued enums in .NET. It is just one C# file that you can copy & paste into your projects, or install via NuGet package named StringEnum. GitHub Repo
Intellisense will suggest the enum name if the class is annotated with the xml comment <completitionlist>. (Works in both C# and VB)
Usage similar to a regular enum:
///<completionlist cref="HexColor"/>
class HexColor : StringEnum<HexColor>
{
public static readonly HexColor Blue = Create("#FF0000");
public static readonly HexColor Green = Create("#00FF00");
public static readonly HexColor Red = Create("#000FF");
}
// Static Parse Method
HexColor.Parse("#FF0000") // => HexColor.Red
HexColor.Parse("#ff0000", caseSensitive: false) // => HexColor.Red
HexColor.Parse("invalid") // => throws InvalidOperationException
// Static TryParse method.
HexColor.TryParse("#FF0000") // => HexColor.Red
HexColor.TryParse("#ff0000", caseSensitive: false) // => HexColor.Red
HexColor.TryParse("invalid") // => null
// Parse and TryParse returns the preexistent instances
object.ReferenceEquals(HexColor.Parse("#FF0000"), HexColor.Red) // => true
// Conversion from your `StringEnum` to `string`
string myString1 = HexColor.Red.ToString(); // => "#FF0000"
string myString2 = HexColor.Red; // => "#FF0000" (implicit cast)
Instalation:
Paste the following StringEnum base class to your project. (latest version)
Or install StringEnum NuGet package, which is based on .Net Standard 1.0 so it runs on .Net Core >= 1.0, .Net Framework >= 4.5, Mono >= 4.6, etc.
/// <summary>
/// Base class for creating string-valued enums in .NET.<br/>
/// Provides static Parse() and TryParse() methods and implicit cast to string.
/// </summary>
/// <example>
/// <code>
/// class Color : StringEnum <Color>
/// {
/// public static readonly Color Blue = Create("Blue");
/// public static readonly Color Red = Create("Red");
/// public static readonly Color Green = Create("Green");
/// }
/// </code>
/// </example>
/// <typeparam name="T">The string-valued enum type. (i.e. class Color : StringEnum<Color>)</typeparam>
public abstract class StringEnum<T> : IEquatable<T> where T : StringEnum<T>, new()
{
protected string Value;
private static Dictionary<string, T> valueDict = new Dictionary<string, T>();
protected static T Create(string value)
{
if (value == null)
return null; // the null-valued instance is null.
var result = new T() { Value = value };
valueDict.Add(value, result);
return result;
}
public static implicit operator string(StringEnum<T> enumValue) => enumValue.Value;
public override string ToString() => Value;
public static bool operator !=(StringEnum<T> o1, StringEnum<T> o2) => o1?.Value != o2?.Value;
public static bool operator ==(StringEnum<T> o1, StringEnum<T> o2) => o1?.Value == o2?.Value;
public override bool Equals(object other) => this.Value.Equals((other as T)?.Value ?? (other as string));
bool IEquatable<T>.Equals(T other) => this.Value.Equals(other.Value);
public override int GetHashCode() => Value.GetHashCode();
/// <summary>
/// Parse the <paramref name="value"/> specified and returns a valid <typeparamref name="T"/> or else throws InvalidOperationException.
/// </summary>
/// <param name="value">The string value representad by an instance of <typeparamref name="T"/>. Matches by string value, not by the member name.</param>
/// <param name="caseSensitive">If true, the strings must match case and takes O(log n). False allows different case but is little bit slower (O(n))</param>
public static T Parse(string value, bool caseSensitive = true)
{
var result = TryParse(value, caseSensitive);
if (result == null)
throw new InvalidOperationException((value == null ? "null" : $"'{value}'") + $" is not a valid {typeof(T).Name}");
return result;
}
/// <summary>
/// Parse the <paramref name="value"/> specified and returns a valid <typeparamref name="T"/> or else returns null.
/// </summary>
/// <param name="value">The string value representad by an instance of <typeparamref name="T"/>. Matches by string value, not by the member name.</param>
/// <param name="caseSensitive">If true, the strings must match case. False allows different case but is slower: O(n)</param>
public static T TryParse(string value, bool caseSensitive = true)
{
if (value == null) return null;
if (valueDict.Count == 0) System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(T).TypeHandle); // force static fields initialization
if (caseSensitive)
{
if (valueDict.TryGetValue(value, out T item))
return item;
else
return null;
}
else
{
// slower O(n) case insensitive search
return valueDict.FirstOrDefault(f => f.Key.Equals(value, StringComparison.OrdinalIgnoreCase)).Value;
// Why Ordinal? => https://esmithy.net/2007/10/15/why-stringcomparisonordinal-is-usually-the-right-choice/
}
}
}
I wanted to post this as a comment to the post quoted below but couldn't because I don't have enough rep. The code contained an error and I wanted to point this out to individuals trying to use this solution:
[TypeConverter(typeof(CustomEnumTypeConverter(typeof(MyEnum))]
public enum MyEnum
{
// The custom type converter will use the description attribute
[Description("A custom description")]
ValueWithCustomDescription,
// This will be exposed exactly.
Exact
}
should be
[TypeConverter(typeof(CustomEnumTypeConverter<MyEnum>))]
public enum MyEnum
{
// The custom type converter will use the description attribute
[Description("A custom description")]
ValueWithCustomDescription,
// This will be exposed exactly.
Exact
}
My variant
public struct Colors
{
private String current;
private static string red = "#ff0000";
private static string green = "#00ff00";
private static string blue = "#0000ff";
private static IList<String> possibleColors;
public static Colors Red { get { return (Colors) red; } }
public static Colors Green { get { return (Colors) green; } }
public static Colors Blue { get { return (Colors) blue; } }
static Colors()
{
possibleColors = new List<string>() {red, green, blue};
}
public static explicit operator String(Colors value)
{
return value.current;
}
public static explicit operator Colors(String value)
{
if (!possibleColors.Contains(value))
{
throw new InvalidCastException();
}
Colors color = new Colors();
color.current = value;
return color;
}
public static bool operator ==(Colors left, Colors right)
{
return left.current == right.current;
}
public static bool operator !=(Colors left, Colors right)
{
return left.current != right.current;
}
public bool Equals(Colors other)
{
return Equals(other.current, current);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (obj.GetType() != typeof(Colors)) return false;
return Equals((Colors)obj);
}
public override int GetHashCode()
{
return (current != null ? current.GetHashCode() : 0);
}
public override string ToString()
{
return current;
}
}
Code looks a bit ugly, but usages of this struct are pretty presentative.
Colors color1 = Colors.Red;
Console.WriteLine(color1); // #ff0000
Colors color2 = (Colors) "#00ff00";
Console.WriteLine(color2); // #00ff00
// Colors color3 = "#0000ff"; // Compilation error
// String color4 = Colors.Red; // Compilation error
Colors color5 = (Colors)"#ff0000";
Console.WriteLine(color1 == color5); // True
Colors color6 = (Colors)"#00ff00";
Console.WriteLine(color1 == color6); // False
Also, I think, if a lot of such enums required, code generation (e.g. T4) might be used.
Option 1:
public sealed class FormsAuth
{
public override string ToString{return "Forms Authtentication";}
}
public sealed class WindowsAuth
{
public override string ToString{return "Windows Authtentication";}
}
public sealed class SsoAuth
{
public override string ToString{return "SSO";}
}
and then
object auth = new SsoAuth(); //or whatever
//...
//...
// blablabla
DoSomethingWithTheAuth(auth.ToString());
Option 2:
public enum AuthenticationMethod
{
FORMS = 1,
WINDOWSAUTHENTICATION = 2,
SINGLESIGNON = 3
}
public class MyClass
{
private Dictionary<AuthenticationMethod, String> map = new Dictionary<AuthenticationMethod, String>();
public MyClass()
{
map.Add(AuthenticationMethod.FORMS,"Forms Authentication");
map.Add(AuthenticationMethod.WINDOWSAUTHENTICATION ,"Windows Authentication");
map.Add(AuthenticationMethod.SINGLESIGNON ,"SSo Authentication");
}
}
If you think about the problem we're trying to solve, it's not an enum we need at all. We need an object that allows a certain number of values to be associated with eachother; in other words, to define a class.
Jakub Šturc's type-safe enum pattern is the best option I see here.
Look at it:
It has a private constructor so only the class itself can define the allowed values.
It is a sealed class so values can't be modifed through inheritence.
It is type-safe, allowing your methods to require only that type.
There is no reflection performance hit incurred by accessing the values.
And lastly, it can be modified to associate more than two fields together, for example a Name, Description, and a numeric Value.
for me, the pragmatic approach is class inside class, sample:
public class MSEModel
{
class WITS
{
public const string DATE = "5005";
public const string TIME = "5006";
public const string MD = "5008";
public const string ROP = "5075";
public const string WOB = "5073";
public const string RPM = "7001";
...
}
Here is yet another way to accomplish the task of associating strings with enums:
struct DATABASE {
public enum enums {NOTCONNECTED, CONNECTED, ERROR}
static List<string> strings =
new List<string>() {"Not Connected", "Connected", "Error"};
public string GetString(DATABASE.enums value) {
return strings[(int)value];
}
}
This method is called like this:
public FormMain() {
DATABASE dbEnum;
string enumName = dbEnum.GetString(DATABASE.enums.NOTCONNECTED);
}
You can group related enums in their own struct. Since this method uses the enum type, you can use Intellisense to display the list of enums when making the GetString() call.
You can optionally use the new operator on the DATABASE struct. Not using it means the strings List is not allocated until the first GetString() call is made.
A lot of great answers here but in my case did not solve what I wanted out of an "string enum", which was:
Usable in a switch statement e.g switch(myEnum)
Can be used in function parameters e.g. foo(myEnum type)
Can be referenced e.g. myEnum.FirstElement
I can use strings e.g. foo("FirstElement") == foo(myEnum.FirstElement)
1,2 & 4 can actually be solved with a C# Typedef of a string (since strings are switchable in c#)
3 can be solved by static const strings. So if you have the same needs, this is the simplest approach:
public sealed class Types
{
private readonly String name;
private Types(String name)
{
this.name = name;
}
public override String ToString()
{
return name;
}
public static implicit operator Types(string str)
{
return new Types(str);
}
public static implicit operator string(Types str)
{
return str.ToString();
}
#region enum
public const string DataType = "Data";
public const string ImageType = "Image";
public const string Folder = "Folder";
#endregion
}
This allows for example:
public TypeArgs(Types SelectedType)
{
Types SelectedType = SelectedType
}
and
public TypeObject CreateType(Types type)
{
switch (type)
{
case Types.ImageType:
//
break;
case Types.DataType:
//
break;
}
}
Where CreateType can be called with a string or a type. However the downside is that any string is automatically a valid enum, this could be modified but then it would require some kind of init function...or possibly make they explicit cast internal?
Now if an int value was important to you (perhaps for comparison speed), you could use some ideas from Jakub Šturc fantastic answer and do something a bit crazy, this is my stab at it:
public sealed class Types
{
private static readonly Dictionary<string, Types> strInstance = new Dictionary<string, Types>();
private static readonly Dictionary<int, Types> intInstance = new Dictionary<int, Types>();
private readonly String name;
private static int layerTypeCount = 0;
private int value;
private Types(String name)
{
this.name = name;
value = layerTypeCount++;
strInstance[name] = this;
intInstance[value] = this;
}
public override String ToString()
{
return name;
}
public static implicit operator Types(int val)
{
Types result;
if (intInstance.TryGetValue(val, out result))
return result;
else
throw new InvalidCastException();
}
public static implicit operator Types(string str)
{
Types result;
if (strInstance.TryGetValue(str, out result))
{
return result;
}
else
{
result = new Types(str);
return result;
}
}
public static implicit operator string(Types str)
{
return str.ToString();
}
public static bool operator ==(Types a, Types b)
{
return a.value == b.value;
}
public static bool operator !=(Types a, Types b)
{
return a.value != b.value;
}
#region enum
public const string DataType = "Data";
public const string ImageType = "Image";
#endregion
}
but of course "Types bob = 4;" would be meaningless unless you had initialized them first which would sort of defeat the point...
But in theory TypeA == TypeB would be quicker...
If I'm understanding you correctly, you can simply use .ToString() to retrieve the name of the enum from the value (Assuming it's already cast as the Enum);
If you had the naked int (lets say from a database or something) you can first cast it to the enum.
Both methods below will get you the enum name.
AuthenticationMethod myCurrentSetting = AuthenticationMethod.FORMS;
Console.WriteLine(myCurrentSetting); // Prints: FORMS
string name = Enum.GetNames(typeof(AuthenticationMethod))[(int)myCurrentSetting-1];
Console.WriteLine(name); // Prints: FORMS
Keep in mind though, the second technique assumes you are using ints and your index is 1 based (not 0 based). The function GetNames also is quite heavy by comparison, you are generating a whole array each time it's called.
As you can see in the first technique, .ToString() is actually called implicitly.
Both of these are already mentioned in the answers of course, I'm just trying to clarify the differences between them.
old post but...
The answer to this may actually be very simple. Use Enum.ToString() function
There are 6 overloads of this function, you can use Enum.Tostring("F") or Enum.ToString() to return the string value. No need to bother with anything else. Here is a working Demo
Note that this solution may not work for all compilers (this demo does not work as expected) but at least it works for the latest compiler.
based on the MSDN: http://msdn.microsoft.com/en-us/library/cc138362.aspx
foreach (string str in Enum.GetNames(typeof(enumHeaderField)))
{
Debug.WriteLine(str);
}
str will be the names of the fields
Well, after reading all of the above I feel that the guys have over complicated the issue of transforming enumerators into strings.
I liked the idea of having attributes over enumerated fields but i think that attributes are mainly used for Meta-data, but in your case i think that all you need is some sort of localization.
public enum Color
{ Red = 1, Green = 2, Blue = 3}
public static EnumUtils
{
public static string GetEnumResourceString(object enumValue)
{
Type enumType = enumValue.GetType();
string value = Enum.GetName(enumValue.GetType(), enumValue);
string resourceKey = String.Format("{0}_{1}", enumType.Name, value);
string result = Resources.Enums.ResourceManager.GetString(resourceKey);
if (string.IsNullOrEmpty(result))
{
result = String.Format("{0}", value);
}
return result;
}
}
Now if we try to call the above method we can call it this way
public void Foo()
{
var col = Color.Red;
Console.WriteLine (EnumUtils.GetEnumResourceString (col));
}
All you need to do is just create a resource file containing all the enumerator values and the corresponding strings
Resource Name Resource Value
Color_Red My String Color in Red
Color_Blue Blueeey
Color_Green Hulk Color
What is actually very nice about that is that it will be very helpful if you need your application to be localized, since all you need to do is just create another resource file with your new language! and Voe-la!
When I am in a situation like that I propose the solution below.
And as a consuming class you could have
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyApp.Dictionaries
{
class Greek
{
public static readonly string Alpha = "Alpha";
public static readonly string Beta = "Beta";
public static readonly string Gamma = "Gamma";
public static readonly string Delta = "Delta";
private static readonly BiDictionary<int, string> Dictionary = new BiDictionary<int, string>();
static Greek() {
Dictionary.Add(1, Alpha);
Dictionary.Add(2, Beta);
Dictionary.Add(3, Gamma);
Dictionary.Add(4, Delta);
}
public static string getById(int id){
return Dictionary.GetByFirst(id);
}
public static int getByValue(string value)
{
return Dictionary.GetBySecond(value);
}
}
}
And using a bidirectional dictionary:
Based on this (https://stackoverflow.com/a/255638/986160) assuming that the keys will be associated with single values in the dictionary and similar to (https://stackoverflow.com/a/255630/986160) but a bit more elegant. This dictionary is also enumerable and you can go back and forth from ints to strings. Also you don't have to have any string in your codebase with the exception of this class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace MyApp.Dictionaries
{
class BiDictionary<TFirst, TSecond> : IEnumerable
{
IDictionary<TFirst, TSecond> firstToSecond = new Dictionary<TFirst, TSecond>();
IDictionary<TSecond, TFirst> secondToFirst = new Dictionary<TSecond, TFirst>();
public void Add(TFirst first, TSecond second)
{
firstToSecond.Add(first, second);
secondToFirst.Add(second, first);
}
public TSecond this[TFirst first]
{
get { return GetByFirst(first); }
}
public TFirst this[TSecond second]
{
get { return GetBySecond(second); }
}
public TSecond GetByFirst(TFirst first)
{
return firstToSecond[first];
}
public TFirst GetBySecond(TSecond second)
{
return secondToFirst[second];
}
public IEnumerator GetEnumerator()
{
return GetFirstEnumerator();
}
public IEnumerator GetFirstEnumerator()
{
return firstToSecond.GetEnumerator();
}
public IEnumerator GetSecondEnumerator()
{
return secondToFirst.GetEnumerator();
}
}
}
For larger string enum sets, the listed examples can become tiresome. If you want a list of status codes, or a list of other string based enums, an attribute system is annoying to use, and a static class with instances of itself is annoying to configure. For my own solution, I make use of T4 templating to make it easier to have string-backed enums. The result comes out similar to how the HttpMethod class works.
You can use it like this:
string statusCode = ResponseStatusCode.SUCCESS; // Automatically converts to string when needed
ResponseStatusCode codeByValueOf = ResponseStatusCode.ValueOf(statusCode); // Returns null if not found
// Implements TypeConverter so you can use it with string conversion methods.
var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(ResponseStatusCode));
ResponseStatusCode code = (ResponseStatusCode) converter.ConvertFromInvariantString(statusCode);
// You can get a full list of the values
bool canIterateOverValues = ResponseStatusCode.Values.Any();
// Comparisons are by value of the "Name" property. Not by memory pointer location.
bool implementsByValueEqualsEqualsOperator = "SUCCESS" == ResponseStatusCode.SUCCESS;
You start out with a Enum.tt file.
<## include file="StringEnum.ttinclude" #>
<#+
public static class Configuration
{
public static readonly string Namespace = "YourName.Space";
public static readonly string EnumName = "ResponseStatusCode";
public static readonly bool IncludeComments = true;
public static readonly object Nodes = new
{
SUCCESS = "The response was successful.",
NON_SUCCESS = "The request was not successful.",
RESOURCE_IS_DISCONTINUED = "The resource requested has been discontinued and can no longer be accessed."
};
}
#>
Then, you add in your StringEnum.ttinclude file.
<## template debug="false" hostspecific="false" language="C#" #>
<## assembly name="System.Core" #>
<## import namespace="System" #>
<## import namespace="System.Linq" #>
<## import namespace="System.Text" #>
<## import namespace="System.Reflection" #>
<## import namespace="System.Collections.Generic" #>
<## output extension=".cs" #>
<## CleanupBehavior processor="T4VSHost" CleanupAfterProcessingtemplate="true" #>
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
namespace <#= Configuration.Namespace #>
{
/// <summary>
/// TypeConverter implementations allow you to use features like string.ToNullable(T).
/// </summary>
public class <#= Configuration.EnumName #>TypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var casted = value as string;
if (casted != null)
{
var result = <#= Configuration.EnumName #>.ValueOf(casted);
if (result != null)
{
return result;
}
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
var casted = value as <#= Configuration.EnumName #>;
if (casted != null && destinationType == typeof(string))
{
return casted.ToString();
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
[TypeConverter(typeof(<#= Configuration.EnumName #>TypeConverter))]
public class <#= Configuration.EnumName #> : IEquatable<<#= Configuration.EnumName #>>
{
//---------------------------------------------------------------------------------------------------
// V A L U E S _ L I S T
//---------------------------------------------------------------------------------------------------
<# Write(Helpers.PrintEnumProperties(Configuration.Nodes)); #>
private static List<<#= Configuration.EnumName #>> _list { get; set; } = null;
public static List<<#= Configuration.EnumName #>> ToList()
{
if (_list == null)
{
_list = typeof(<#= Configuration.EnumName #>).GetFields().Where(x => x.IsStatic && x.IsPublic && x.FieldType == typeof(<#= Configuration.EnumName #>))
.Select(x => x.GetValue(null)).OfType<<#= Configuration.EnumName #>>().ToList();
}
return _list;
}
public static List<<#= Configuration.EnumName #>> Values()
{
return ToList();
}
/// <summary>
/// Returns the enum value based on the matching Name of the enum. Case-insensitive search.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static <#= Configuration.EnumName #> ValueOf(string key)
{
return ToList().FirstOrDefault(x => string.Compare(x.Name, key, true) == 0);
}
//---------------------------------------------------------------------------------------------------
// I N S T A N C E _ D E F I N I T I O N
//---------------------------------------------------------------------------------------------------
public string Name { get; private set; }
public string Description { get; private set; }
public override string ToString() { return this.Name; }
/// <summary>
/// Implcitly converts to string.
/// </summary>
/// <param name="d"></param>
public static implicit operator string(<#= Configuration.EnumName #> d)
{
return d.ToString();
}
/// <summary>
/// Compares based on the == method. Handles nulls gracefully.
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static bool operator !=(<#= Configuration.EnumName #> a, <#= Configuration.EnumName #> b)
{
return !(a == b);
}
/// <summary>
/// Compares based on the .Equals method. Handles nulls gracefully.
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static bool operator ==(<#= Configuration.EnumName #> a, <#= Configuration.EnumName #> b)
{
return a?.ToString() == b?.ToString();
}
/// <summary>
/// Compares based on the .ToString() method
/// </summary>
/// <param name="o"></param>
/// <returns></returns>
public override bool Equals(object o)
{
return this.ToString() == o?.ToString();
}
/// <summary>
/// Compares based on the .ToString() method
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
public bool Equals(<#= Configuration.EnumName #> other)
{
return this.ToString() == other?.ToString();
}
/// <summary>
/// Compares based on the .Name property
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return this.Name.GetHashCode();
}
}
}
<#+
public static class Helpers
{
public static string PrintEnumProperties(object nodes)
{
string o = "";
Type nodesTp = Configuration.Nodes.GetType();
PropertyInfo[] props = nodesTp.GetProperties().OrderBy(p => p.Name).ToArray();
for(int i = 0; i < props.Length; i++)
{
var prop = props[i];
if (Configuration.IncludeComments)
{
o += "\r\n\r\n";
o += "\r\n ///<summary>";
o += "\r\n /// "+Helpers.PrintPropertyValue(prop, Configuration.Nodes);
o += "\r\n ///</summary>";
}
o += "\r\n public static readonly "+Configuration.EnumName+" "+prop.Name+ " = new "+Configuration.EnumName+"(){ Name = \""+prop.Name+"\", Description = "+Helpers.PrintPropertyValue(prop, Configuration.Nodes)+ "};";
}
o += "\r\n\r\n";
return o;
}
private static Dictionary<string, string> GetValuesMap()
{
Type nodesTp = Configuration.Nodes.GetType();
PropertyInfo[] props= nodesTp.GetProperties();
var dic = new Dictionary<string,string>();
for(int i = 0; i < props.Length; i++)
{
var prop = nodesTp.GetProperties()[i];
dic[prop.Name] = prop.GetValue(Configuration.Nodes).ToString();
}
return dic;
}
public static string PrintMasterValuesMap(object nodes)
{
Type nodesTp = Configuration.Nodes.GetType();
PropertyInfo[] props= nodesTp.GetProperties();
string o = " private static readonly Dictionary<string, string> ValuesMap = new Dictionary<string, string>()\r\n {";
for(int i = 0; i < props.Length; i++)
{
var prop = nodesTp.GetProperties()[i];
o += "\r\n { \""+prop.Name+"\", "+(Helpers.PrintPropertyValue(prop,Configuration.Nodes)+" },");
}
o += ("\r\n };\r\n");
return o;
}
public static string PrintPropertyValue(PropertyInfo prop, object objInstance)
{
switch(prop.PropertyType.ToString()){
case "System.Double":
return prop.GetValue(objInstance).ToString()+"D";
case "System.Float":
return prop.GetValue(objInstance).ToString()+"F";
case "System.Decimal":
return prop.GetValue(objInstance).ToString()+"M";
case "System.Long":
return prop.GetValue(objInstance).ToString()+"L";
case "System.Boolean":
case "System.Int16":
case "System.Int32":
return prop.GetValue(objInstance).ToString().ToLowerInvariant();
case "System.String":
return "\""+prop.GetValue(objInstance)+"\"";
}
return prop.GetValue(objInstance).ToString();
}
public static string _ (int numSpaces)
{
string o = "";
for(int i = 0; i < numSpaces; i++){
o += " ";
}
return o;
}
}
#>
Finally, you recompile your Enum.tt file and the output looks like this:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Linq;
using System.Collections.Generic;
namespace YourName.Space
{
public class ResponseStatusCode
{
//---------------------------------------------------------------------------------------------------
// V A L U E S _ L I S T
//---------------------------------------------------------------------------------------------------
///<summary>
/// "The response was successful."
///</summary>
public static readonly ResponseStatusCode SUCCESS = new ResponseStatusCode(){ Name = "SUCCESS", Description = "The response was successful."};
///<summary>
/// "The request was not successful."
///</summary>
public static readonly ResponseStatusCode NON_SUCCESS = new ResponseStatusCode(){ Name = "NON_SUCCESS", Description = "The request was not successful."};
///<summary>
/// "The resource requested has been discontinued and can no longer be accessed."
///</summary>
public static readonly ResponseStatusCode RESOURCE_IS_DISCONTINUED = new ResponseStatusCode(){ Name = "RESOURCE_IS_DISCONTINUED", Description = "The resource requested has been discontinued and can no longer be accessed."};
private static List<ResponseStatusCode> _list { get; set; } = null;
public static List<ResponseStatusCode> ToList()
{
if (_list == null)
{
_list = typeof(ResponseStatusCode).GetFields().Where(x => x.IsStatic && x.IsPublic && x.FieldType == typeof(ResponseStatusCode))
.Select(x => x.GetValue(null)).OfType<ResponseStatusCode>().ToList();
}
return _list;
}
public static List<ResponseStatusCode> Values()
{
return ToList();
}
/// <summary>
/// Returns the enum value based on the matching Name of the enum. Case-insensitive search.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static ResponseStatusCode ValueOf(string key)
{
return ToList().FirstOrDefault(x => string.Compare(x.Name, key, true) == 0);
}
//---------------------------------------------------------------------------------------------------
// I N S T A N C E _ D E F I N I T I O N
//---------------------------------------------------------------------------------------------------
public string Name { get; set; }
public string Description { get; set; }
public override string ToString() { return this.Name; }
/// <summary>
/// Implcitly converts to string.
/// </summary>
/// <param name="d"></param>
public static implicit operator string(ResponseStatusCode d)
{
return d.ToString();
}
/// <summary>
/// Compares based on the == method. Handles nulls gracefully.
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static bool operator !=(ResponseStatusCode a, ResponseStatusCode b)
{
return !(a == b);
}
/// <summary>
/// Compares based on the .Equals method. Handles nulls gracefully.
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static bool operator ==(ResponseStatusCode a, ResponseStatusCode b)
{
return a?.ToString() == b?.ToString();
}
/// <summary>
/// Compares based on the .ToString() method
/// </summary>
/// <param name="o"></param>
/// <returns></returns>
public override bool Equals(object o)
{
return this.ToString() == o?.ToString();
}
/// <summary>
/// Compares based on the .Name property
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return this.Name.GetHashCode();
}
}
}

Categories

Resources