Сохраняя идею конвертера, чтобы пропустить блок переключателей, вы можете использовать концепцию Duck Typing. По сути, вы хотите превратить строку в X, поэтому вы создаете метод, который будет вызывать X.TryParse (string, out X x), если у X есть TryParse, в противном случае вы просто не будете беспокоиться (или я полагаю, вы могли бы бросить ошибка). Как бы вы это сделали? Отражение и обобщения.
По сути, у вас будет метод, который будет принимать тип и использовать отражение, чтобы увидеть, есть ли у него TryParse. Если вы нашли такой метод, вы вызываете его и возвращаете все, что удалось получить TryParse. Это хорошо работает практически со всеми типами значений, такими как, скажем, Decimal или DateTime.
public static class ConvertFromString
{
public static T? ConvertTo<T>(this String numberToConvert) where T : struct
{
T? returnValue = null;
MethodInfo neededInfo = GetCorrectMethodInfo(typeof(T));
if (neededInfo != null && !numberToConvert.IsNullOrEmpty())
{
T output = default(T);
object[] paramsArray = new object[2] { numberToConvert, output };
returnValue = new T();
object returnedValue = neededInfo.Invoke(returnValue.Value, paramsArray);
if (returnedValue is Boolean && (Boolean)returnedValue)
{
returnValue = (T)paramsArray[1];
}
else
{
returnValue = null;
}
}
return returnValue;
}
}
Где GetCorrectMethodInfo будет выглядеть примерно так:
private static MethodInfo GetCorrectMethodInfo(Type typeToCheck)
{
MethodInfo returnValue = someCache.Get(typeToCheck.FullName);
if(returnValue == null)
{
Type[] paramTypes = new Type[2] { typeof(string), typeToCheck.MakeByRefType() };
returnValue = typeToCheck.GetMethod("TryParse", paramTypes);
if (returnValue != null)
{
CurrentCache.Add(typeToCheck.FullName, returnValue);
}
}
return returnValue;
}
И использование будет:
decimal? converted = someString.ConvertTo<decimal>();
Я ненавижу подключать себя, но я полностью объяснил это здесь:
GetCorrectMethodInfo
Остальное