СУХОЙ (не повторяйся) код
Скажем, если вы хотите изменить значение, font-size: 24px
, вы можете сделать n раз, чем один раз в CSS , Плюс размер кода тоже меньше.
Каскадирование / переопределение
Я бы не стал говорить о том, чтобы поместить CSS в отдельный файл, но, безусловно, встроенные стили не одобряются, поскольку встроенные стили нельзя переопределять, кроме как с помощью !important
.
Презентация / Разделение контента
Вы действительно должны разделить оба.
I like to use properties in a class instead of methods, since they look more enum-like.
Here's a example for a Logger:
public class LogCategory
{
private LogCategory(string value) { Value = value; }
public string Value { get; set; }
public static LogCategory Trace { get { return new LogCategory("Trace"); } }
public static LogCategory Debug { get { return new LogCategory("Debug"); } }
public static LogCategory Info { get { return new LogCategory("Info"); } }
public static LogCategory Warning { get { return new LogCategory("Warning"); } }
public static LogCategory Error { get { return new LogCategory("Error"); } }
}
Pass in type-safe string values as a parameter:
public static void Write(string message, LogCategory logCategory)
{
var log = new LogEntry { Message = message };
Logger.Write(log, logCategory.Value);
}
Usage:
Logger.Write("This is almost like an enum.", LogCategory.Info);
Мой первый вопрос - у Вас есть доступ к самой Базе данных? Это должно быть нормализовано в базе данных, идеально, иначе, любое решение будет подверженным ошибке. По моему опыту, поля данных, полные "OEM" и "CMB", имеют тенденцию завершать вещи наличия как "oem" и другие 'загаженные данные', смешанные в со временем.... Если можно нормализовать его, Вы могли бы использовать ключ в таблице, содержащей элементы как Ваше Перечисление, и Вы сделаны с намного более чистой структурой.
, Если бы это не доступно, я сделал бы Ваше Перечисление и сделал бы класс для парсинга строки в Перечисление для Вас. Это, по крайней мере, дало бы Вам некоторую гибкость в обработке нестандартных записей и намного большей гибкости для захвата или ошибок из-за неправильного обращения, чем выполнение любого из обходных решений с помощью Перечисления. Синтаксический анализ/Отражение/и т.д. Словарь работал бы, но мог сломаться, если бы у Вас когда-нибудь есть проблемы случая, и т.д.
я рекомендовал бы писать класс, таким образом, можно сделать:
// I renamed this to GroupType, since it sounds like each element has a single type...
GroupType theType = GroupTypeParser.GetGroupType(theDBString);
Это сохраняет большую часть Вашей удобочитаемости, не имея необходимость изменять DB.
Я просто создал бы словарь и использовал бы код как ключ.
Редактирование: Для обращения к комментарию о выполнении обратного поиска (находящий ключ) это не было бы ужасно эффективно. Если бы это необходимо, я записал бы новый класс для обработки его.
Я превратил бы его в класс избегание перечисления в целом. И затем с использованием typehandler Вы могли создать объект при захвате его от дб.
IE:
public class Group
{
public string Value{ get; set; }
public Group( string value ){ Value = value; }
public static Group TheGroup() { return new Group("OEM"); }
public static Group OtherGroup() { return new Group("CMB"); }
}
Вы рассмотрели таблицу поиска с помощью Словаря?
enum GroupTypes
{
TheGroup,
TheOtherGroup
}
Dictionary<string, GroupTypes> GroupTypeLookup = new Dictionary<string, GroupTypes>();
// initialize lookup table:
GroupTypeLookup.Add("OEM", TheGroup);
GroupTypeLookup.Add("CMB", TheOtherGroup);
можно тогда использовать GroupTypeLookup. TryGetValue () для поиска строки, когда Вы читаете его.
Попытайтесь добавить константы к статическому классу. Вы не заканчиваете с Типом, но у Вас будут читаемые, организованные константы:
public static class GroupTypes {
public const string TheGroup = "OEM";
public const string TheOtherGroup = "CMB";
}
Используйте класс.
Редактирование: Лучший пример
class StarshipType
{
private string _Name;
private static List<StarshipType> _StarshipTypes = new List<StarshipType>();
public static readonly StarshipType Ultralight = new StarshipType("Ultralight");
public static readonly StarshipType Light = new StarshipType("Light");
public static readonly StarshipType Mediumweight = new StarshipType("Mediumweight");
public static readonly StarshipType Heavy = new StarshipType("Heavy");
public static readonly StarshipType Superheavy = new StarshipType("Superheavy");
public string Name
{
get { return _Name; }
private set { _Name = value; }
}
public static IList<StarshipType> StarshipTypes
{
get { return _StarshipTypes; }
}
private StarshipType(string name, int systemRatio)
{
Name = name;
_StarshipTypes.Add(this);
}
public static StarshipType Parse(string toParse)
{
foreach (StarshipType s in StarshipTypes)
{
if (toParse == s.Name)
return s;
}
throw new FormatException("Could not parse string.");
}
}
Создайте второе перечисление для Вашего DB, содержащего следующее:
enum DBGroupTypes
{
OEM = 0,
CMB = 1
}
Теперь, можно использовать Перечисление. Синтаксический анализ для получения корректного значения DBGroupTypes от строк "OEM" и "CMB". Можно тогда преобразовать тех, которых к интервалу и получить правильные значения от правильного перечисления Вы хотите использовать далее в Вашей модели.
Можно добавить атрибуты к объектам в перечислении и затем использовать отражение для получения значений от атрибутов.
необходимо было бы использовать "полевой" спецификатор для применения атрибутов, как так:
enum GroupTypes
{
[field:Description("OEM")]
TheGroup,
[field:Description("CMB")]
TheOtherGroup
}
Вы тогда размышляли бы над статическими полями типа перечисления (в этом случае GroupTypes) и добрались бы DescriptionAttribute
для значения, Вы искали использование отражения:
public static DescriptionAttribute GetEnumDescriptionAttribute<T>(
this T value) where T : struct
{
// The type of the enum, it will be reused.
Type type = typeof(T);
// If T is not an enum, get out.
if (!type.IsEnum)
throw new InvalidOperationException(
"The type parameter T must be an enum type.");
// If the value isn't defined throw an exception.
if (!Enum.IsDefined(type, value))
throw new InvalidEnumArgumentException(
"value", Convert.ToInt32(value), type);
// Get the static field for the value.
FieldInfo fi = type.GetField(value.ToString(),
BindingFlags.Static | BindingFlags.Public);
// Get the description attribute, if there is one.
return fi.GetCustomAttributes(typeof(DescriptionAttribute), true).
Cast<DescriptionAttribute>().SingleOrDefault();
}
я решил возвратиться DescriptionAttribute
самостоятельно выше, если Вы хотите быть в состоянии определить, применяется ли атрибут даже.
Вы могли также использовать дополнительную модель:
public enum MyEnum
{
[Description("String 1")]
V1= 1,
[Description("String 2")]
V2= 2
}
Ваше Дополнительное использование Класса
public static class MyEnumExtensions
{
public static string ToDescriptionString(this MyEnum val)
{
DescriptionAttribute[] attributes = (DescriptionAttribute[])val
.GetType()
.GetField(val.ToString())
.GetCustomAttributes(typeof(DescriptionAttribute), false);
return attributes.Length > 0 ? attributes[0].Description : string.Empty;
}
}
:
MyEnum myLocal = MyEnum.V1;
print(myLocal.ToDescriptionString());
Добавление этого класса
public class DatabasePreference {
public DatabasePreference([CallerMemberName] string preferenceName = "") {
PreferenceName = preferenceName;
}
public string PreferenceName;
}
Эта работа использует CallerMemberName
для уменьшения кодирования
Используя:
//Declare names
public static DatabasePreference ScannerDefaultFlashLight = new DatabasePreference();
public static DatabasePreference ScannerQrCodes = new DatabasePreference();
public static DatabasePreference Scanner1dCodes = new DatabasePreference();
Тест это:
Console.WriteLine(ScannerDefaultFlashLight.PreferenceName);
Console.WriteLine(ScannerDefaultFlashLight.Scanner1dCodes);
вывод:
ScannerDefaultFlashLight
Scanner1dCodes
На самом деле вы можете сделать это очень легко. Используйте следующий код.
enum GroupTypes
{
OEM,
CMB
};
Затем, если вы хотите получить строковое значение каждого элемента перечисления, просто используйте следующую строку кода.
String oemString = Enum.GetName(typeof(GroupTypes), GroupTypes.OEM);
Я успешно использовал этот метод в прошлом, и я также использовал Класс констант для хранения строковых констант, оба работают довольно хорошо, но я предпочитаю этот.
Вот метод расширения, который я использовал для получения значения перечисления в виде строки. Сначала перечисление.
public enum DatabaseEnvironment
{
[Description("AzamSharpBlogDevDatabase")]
Development = 1,
[Description("AzamSharpBlogQADatabase")]
QualityAssurance = 2,
[Description("AzamSharpBlogTestDatabase")]
Test = 3
}
Атрибут Description взят из System.ComponentModel.
А вот мой метод расширения:
public static string GetValueAsString(this DatabaseEnvironment environment)
{
// get the field
var field = environment.GetType().GetField(environment.ToString());
var customAttributes = field.GetCustomAttributes(typeof (DescriptionAttribute), false);
if(customAttributes.Length > 0)
{
return (customAttributes[0] as DescriptionAttribute).Description;
}
else
{
return environment.ToString();
}
}
Теперь вы можете получить доступ к перечислению как строковому значению, используя следующий код:
[TestFixture]
public class when_getting_value_of_enum
{
[Test]
public void should_get_the_value_as_string()
{
Assert.AreEqual("AzamSharpBlogTestDatabase",DatabaseEnvironment.Test.GetValueAsString());
}
}
Новый в .Net Core 3.0/C# 8.0 (если Ваша рабочая среда позволяет Вам обновлять свой проект) является кратким оператором переключения, который смотрит несколько перечислимый выход. В конце дня это - тот же старый скучный оператор переключения, который мы использовали в течение многих лет.
Только реальная разница здесь - то, что оператор переключения получил новый иск.
public static RGBColor FromRainbow(Rainbow colorBand) =>
colorBand switch
{
Rainbow.Red => new RGBColor(0xFF, 0x00, 0x00),
Rainbow.Orange => new RGBColor(0xFF, 0x7F, 0x00),
Rainbow.Yellow => new RGBColor(0xFF, 0xFF, 0x00),
Rainbow.Green => new RGBColor(0x00, 0xFF, 0x00),
Rainbow.Blue => new RGBColor(0x00, 0x00, 0xFF),
Rainbow.Indigo => new RGBColor(0x4B, 0x00, 0x82),
Rainbow.Violet => new RGBColor(0x94, 0x00, 0xD3),
_ => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)),
};
Вы заметите, что код, выше которого я скопировал от здесь , на самом деле использует перечисление в качестве параметрического усилителя.
Это не точно, что Вы хотите (и доверяйте мне, я хотел что-то вроде подобного тому, что OP запрашивает в течение долгого времени), но я на самом деле чувствую, что это - своего рода оливковая ветвь от MS. JMO.
Hope это помогает кому-то!