Я пытаюсь объединить несколько похожих методов в общий метод. У меня есть несколько методов, которые возвращают значение строки запроса или null, если эта строка запроса не существует или имеет неправильный формат. Это было бы достаточно просто, если бы все типы изначально допускали значение NULL, но я должен использовать универсальный тип, допускающий значение NULL, для целых чисел и дат.
Вот что у меня есть сейчас. Однако он вернет 0, если числовое значение недействительно, и, к сожалению, это допустимое значение в моих сценариях. Кто-нибудь может мне помочь? Благодаря!
public static T GetQueryString<T>(string key) where T : IConvertible
{
T result = default(T);
if (String.IsNullOrEmpty(HttpContext.Current.Request.QueryString[key]) == false)
{
string value = HttpContext.Current.Request.QueryString[key];
try
{
result = (T)Convert.ChangeType(value, typeof(T));
}
catch
{
//Could not convert. Pass back default value...
result = default(T);
}
}
return result;
}
ChangeType
сбое.Ответы:
Что, если вы указали значение по умолчанию для возврата вместо использования по умолчанию (T)?
public static T GetQueryString<T>(string key, T defaultValue) {...}
Это также упрощает вызов:
var intValue = GetQueryString("intParm", Int32.MinValue); var strValue = GetQueryString("strParm", ""); var dtmValue = GetQueryString("dtmPatm", DateTime.Now); // eg use today's date if not specified
Обратной стороной является то, что вам нужны магические значения для обозначения недопустимых / отсутствующих значений строки запроса.
источник
long ? test
где по умолчанию должно быть nullЗнаю, знаю, но ...
public static bool TryGetQueryString<T>(string key, out T queryString)
источник
Try
-Pattern должен быть хорошо известен любому разработчику .NET. Это неплохо, если вы спросите меня. В F # или NET 4.0 вы должны использовать Option (или Choice)Что насчет этого? Измените тип возврата с
T
наNullable<T>
public static Nullable<T> GetQueryString<T>(string key) where T : struct, IConvertible { T result = default(T); if (String.IsNullOrEmpty(HttpContext.Current.Request.QueryString[key]) == false) { string value = HttpContext.Current.Request.QueryString[key]; try { result = (T)Convert.ChangeType(value, typeof(T)); } catch { //Could not convert. Pass back default value... result = default(T); } } return result; }
источник
where T : struct
.string
этоnullable
ценностьВы можете использовать своего рода монаду Maybe (хотя я бы предпочел ответ Джея)
public class Maybe<T> { private readonly T _value; public Maybe(T value) { _value = value; IsNothing = false; } public Maybe() { IsNothing = true; } public bool IsNothing { get; private set; } public T Value { get { if (IsNothing) { throw new InvalidOperationException("Value doesn't exist"); } return _value; } } public override bool Equals(object other) { if (IsNothing) { return (other == null); } if (other == null) { return false; } return _value.Equals(other); } public override int GetHashCode() { if (IsNothing) { return 0; } return _value.GetHashCode(); } public override string ToString() { if (IsNothing) { return ""; } return _value.ToString(); } public static implicit operator Maybe<T>(T value) { return new Maybe<T>(value); } public static explicit operator T(Maybe<T> value) { return value.Value; } }
Ваш метод будет выглядеть так:
public static Maybe<T> GetQueryString<T>(string key) where T : IConvertible { if (String.IsNullOrEmpty(HttpContext.Current.Request.QueryString[key]) == false) { string value = HttpContext.Current.Request.QueryString[key]; try { return (T)Convert.ChangeType(value, typeof(T)); } catch { //Could not convert. Pass back default value... return new Maybe<T>(); } } return new Maybe<T>(); }
источник
Convert.ChangeType()
некорректно обрабатывает типы или перечисления, допускающие значение NULL, в .NET 2.0 BCL (хотя я думаю, что это исправлено для BCL 4.0). Вместо того, чтобы усложнять внешнюю реализацию, заставьте конвертер выполнять больше работы за вас. Вот реализация, которую я использую:public static class Converter { public static T ConvertTo<T>(object value) { return ConvertTo(value, default(T)); } public static T ConvertTo<T>(object value, T defaultValue) { if (value == DBNull.Value) { return defaultValue; } return (T) ChangeType(value, typeof(T)); } public static object ChangeType(object value, Type conversionType) { if (conversionType == null) { throw new ArgumentNullException("conversionType"); } // if it's not a nullable type, just pass through the parameters to Convert.ChangeType if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { // null input returns null output regardless of base type if (value == null) { return null; } // it's a nullable type, and not null, which means it can be converted to its underlying type, // so overwrite the passed-in conversion type with this underlying type conversionType = Nullable.GetUnderlyingType(conversionType); } else if (conversionType.IsEnum) { // strings require Parse method if (value is string) { return Enum.Parse(conversionType, (string) value); } // primitive types can be instantiated using ToObject else if (value is int || value is uint || value is short || value is ushort || value is byte || value is sbyte || value is long || value is ulong) { return Enum.ToObject(conversionType, value); } else { throw new ArgumentException(String.Format("Value cannot be converted to {0} - current type is " + "not supported for enum conversions.", conversionType.FullName)); } } return Convert.ChangeType(value, conversionType); } }
Тогда ваша реализация GetQueryString <T> может быть:
public static T GetQueryString<T>(string key) { T result = default(T); string value = HttpContext.Current.Request.QueryString[key]; if (!String.IsNullOrEmpty(value)) { try { result = Converter.ConvertTo<T>(value); } catch { //Could not convert. Pass back default value... result = default(T); } } return result; }
источник
Мне нравится начинать с такого класса, как этот class settings {public int X {get; set;} public string Y {get; набор; } // повторяем при необходимости
public settings() { this.X = defaultForX; this.Y = defaultForY; // repeat ... } public void Parse(Uri uri) { // parse values from query string. // if you need to distinguish from default vs. specified, add an appropriate property }
Это хорошо сработало на сотнях проектов. Вы можете использовать одно из многих других решений для синтаксического анализа значений.
источник