Ваша проблема в том, что «Emp Name» (имя столбца) содержит пробел и должно быть заключено в квадратные скобки в выражении фильтра:
strFilter= strFilter+ " and [Emp Name] = '" + Session["SampleSession"].ToString() + "' ";
Попробуйте безопасное с точки зрения типов перечисление шаблон.
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;
}
}
<час> Обновление Явный (или неявный) преобразование типов может быть сделано [1 111]
добавляющее статическое поле с отображением
private static readonly Dictionary<string, AuthenticationMethod> instance = new Dictionary<string,AuthenticationMethod>();
заполнение этого отображения в конструкторе экземпляра
instance[name] = this;
и добавление пользовательский оператор
public static explicit operator AuthenticationMethod(string str)
{
AuthenticationMethod result;
if (instance.TryGetValue(str, out result))
return result;
else
throw new InvalidCastException();
}
Опция 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";}
}
и затем
object auth = new SsoAuth(); //or whatever
//...
//...
// blablabla
DoSomethingWithTheAuth(auth.ToString());
Опция 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");
}
}
Используйте метод
Enum.GetName(Type MyEnumType, object enumvariable)
как в (Примите Shipper
, определенное Перечисление)
Shipper x = Shipper.FederalExpress;
string s = Enum.GetName(typeof(Shipper), x);
существует набор других статических методов для Класса Enum, который стоит исследовать также...
Можно сослаться на имя, а не значение при помощи ToString ()
Console.WriteLine("Auth method: {0}", AuthenticationMethod.Forms.ToString());
, документация здесь:
http://msdn.microsoft.com/en-us/library/16c1xs4z.aspx
... и если Вы называете свои перечисления в Pascal-регистре (как я делаю - такие как ThisIsMyEnumValue = 1 и т.д.) тогда Вы могли использовать очень простой regex для печати дружественной формы:
static string ToFriendlyCase(this string EnumString)
{
return Regex.Replace(EnumString, "(?!^)([A-Z])", " $1");
}
, который можно легко назвать от любой строки:
Console.WriteLine("ConvertMyCrazyPascalCaseSentenceToFriendlyCase".ToFriendlyCase());
Выводы:
Преобразовывают Мое Сумасшедшее Предложение Pascal-регистра В Дружественный Случай
, Который сохраняет выполнение полностью вокруг зданий, создающих пользовательские атрибуты и присоединяющих их к Вашим перечислениям или использующих таблицы поиска для бракосочетания на перечислении значений с дружественной строкой и лучший из всего, что это сам управление и может использоваться на любой строке Pascal-регистра, которая является бесконечно более допускающей повторное использование. Конечно, это не позволяет Вам иметь отличающийся дружественное имя, чем Ваше перечисление, которое действительно обеспечивает Ваше решение.
мне действительно нравится Ваше исходное решение хотя за более сложные сценарии все же. Вы могли взять свое решение один шаг вперед и сделать Ваш GetStringValue дополнительным методом Вашего перечисления, и затем Вы не должны будете ссылаться на него как 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;
}
Вы могли тогда получить доступ к нему легко прямо от Вашего перечислимого экземпляра:
Console.WriteLine(AuthenticationMethod.SSO.GetStringValue());
я соглашаюсь с Keith, но я (еще) не могу голосовать.
я использую статический метод и swith оператор для возврата точно, что я хочу. В базе данных я храню tinyint, и мой код только использует фактическое перечисление, таким образом, строки для требований UI. После того, как многочисленное тестирование этого привело к лучшей производительности и большей части управления выводом.
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;
}
}
Однако некоторыми учетными записями, это приводит к возможному кошмару обслуживания и некоторому запаху кода. Я пытаюсь бдительно следить для перечислений, которые длинны и много перечислений или тех, которые часто изменяются. Иначе это было отличным решением для меня.
Я использую атрибут Описания от Системы. Пространство имен ComponentModel. Просто украсьте перечисление и затем используйте этот код для получения его:
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();
}
Как пример:
public enum Cycle : int
{
[Description("Daily Cycle")]
Daily = 1,
Weekly,
Monthly
}
Этот код приятно обслуживает перечисления, где Вы не нуждаетесь в "Дружественном имени" и возвратите просто.ToString () перечисления.
Когда я сталкиваюсь с этой проблемой, существует несколько вопросов, на которые я пытаюсь найти ответы сначала:
самый простой способ сделать это с Enum.GetValue
(и круглое смещение поддержки использование Enum.Parse
). Это также часто стоит создать TypeConverter
, как Steve Mitcham предполагает, для поддержки привязки UI. (Не необходимо создать TypeConverter
при использовании окон свойств который является одной из хороших вещей об окнах свойств. Хотя лорд знает, что у них есть свои собственные проблемы.)
В целом, если ответы на вышеупомянутые вопросы предполагают, что это не собирается работать, мой следующий шаг должен создать и заполнить помехи Dictionary<MyEnum, string>
, или возможно Dictionary<Type, Dictionary<int, string>>
. Я склонен пропускать промежуточное звено decorate-the-code-with-attributes шаг, потому что, что обычно снижается, пика затем является потребностью изменить дружественные значения после развертывания (часто, но не всегда, из-за локализации).
К сожалению, отражение для получения атрибутов на перечислениях является довольно медленным:
Посмотрите этот вопрос: Кто-либо знает быстрый способ добраться до пользовательских атрибутов на перечислении значений?
Эти .ToString()
является довольно медленным на перечислениях также.
можно записать дополнительные методы для перечислений хотя:
public static string GetName( this MyEnum input ) {
switch ( input ) {
case MyEnum.WINDOWSAUTHENTICATION:
return "Windows";
//and so on
}
}
Это не является большим, но будет быстрым и не потребует отражения для атрибутов или имени поля.
<час>Обновление C#6
, Если можно использовать C#6 тогда новое nameof
работы оператора для перечислений, таким образом nameof(MyEnum.WINDOWSAUTHENTICATION)
будет преобразован в "WINDOWSAUTHENTICATION"
в время компиляции , делая самым быстрым способом получить перечислимые имена.
Примечание, что это преобразует явное перечисление во встроенную константу, таким образом, это не будет работать на перечисления, которые Вы имеете в переменной. Так:
nameof(AuthenticationMethod.FORMS) == "FORMS"
, Но...
var myMethod = AuthenticationMethod.FORMS;
nameof(myMethod) == "myMethod"
Я использую комбинацию нескольких из предложений выше, объединенный с некоторым кэшированием. Теперь, я получил идею от некоторого кода, что я нашел где-нибудь в сети, но я не могу ни помнить, где я получил его, или найдите его. Таким образом, если кто-либо когда-нибудь находит что-то, что выглядит подобным, прокомментируйте с атрибуцией.
Так или иначе, использование включает конвертеры типов, поэтому если Вы связываете с UI, это 'просто работает'. Вы можете расширенный с помощью шаблона Jakub для быстрого поиска кода путем инициализации из конвертера типов в статические методы.
основное использование было бы похоже на это
[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
}
, код для пользовательского перечислимого конвертера типов следует:
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);
}
}
}
Я создал базовый класс для создания перечислений со знаком строки в.NET. Это - всего один файл C#, что можно скопировать & вставьте в свои проекты или установку через пакет NuGet, названный StringEnum. GitHub Repo
<completitionlist>
. (Работы и в C# и в VB)
///<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)
.Net Standard 1.0
, таким образом, это работает .Net Core
> = 1.0, .Net Framework
> = 4.5, Mono
> = 4.6, и т.д. /// <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/
}
}
}
Если вы думаете о проблеме, которую мы пытаемся решить, это совсем не перечисление, которое нам нужно. Нам нужен объект, который позволяет связать определенное количество значений друг с другом; другими словами, чтобы определить класс.
Типобезопасный шаблон перечисления Якуба Штурца - лучший вариант, который я вижу здесь.
Посмотрите на него:
на основе MSDN: http://msdn.microsoft.com/en-us/library/cc138362.aspx
foreach (string str in Enum.GetNames(typeof(enumHeaderField)))
{
Debug.WriteLine(str);
}
str будут именами полей
op,
вызов, потому что существуют типы, которые перегрузка обработала по шаблонуop,
и которые принимают флаг как второй аргумент (какdel << a, b;
, который имеетdelim operator,(delim,T const&);
). Так выполнение(bar(t), flag())
привело бы к неоднозначности. Мы также couldn' t подкачивают порядок, потому чтоbar(t)
мог иметь типvoid
. При наличииop,
флаг принятия, поскольку первый аргумент гораздо менее вероятен, конечно - таким образом что вещь с тремя путями:) – Johannes Schaub - litb 7 September 2009 в 03:51